home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_glimpse.idb / usr / freeware / src / glimpse-3.0 / agrep / agrep.c.z / agrep.c
C/C++ Source or Header  |  1997-09-09  |  103KB  |  3,445 lines

  1.  
  2. /*
  3.  * bgopal: (1993-4) added a library interface and removed some bugs: also
  4.  * selectively modified many routines to work with our text-compression algo.
  5.  */
  6. #include "agrep.h"
  7. #include "checkfile.h"
  8.  
  9. #define PRINT(s)
  10.  
  11. extern char **environ;
  12. extern int errno;
  13. int pattern_index;    /* index in argv where the pattern is */
  14.  
  15. int glimpse_isserver=0;    /* so that there is no user interaction */
  16. int glimpse_call = 0;    /* So that usage message is not printed twice */
  17. int glimpse_clientdied=0;/* to quit search if glimpseserver's client dies */
  18. int  agrep_initialfd;    /* Where does input come from? File/Memory? */
  19. CHAR *agrep_inbuffer;
  20. int  agrep_inlen;
  21. int  agrep_inpointer;
  22.  
  23. FILE *agrep_finalfp;    /* Where does output go to? File/Memory? */
  24. CHAR *agrep_outbuffer;
  25. int  agrep_outlen;
  26. int  agrep_outpointer;
  27.  
  28. int  execfd;    /* used by exec called within agrep_search, set in agrep_init */
  29. int  multifd = -1; /* fd for multipattern search used in ^^ , set in   ^^^^^^^^ */
  30. extern char *pat_spool;
  31. #if    DOTCOMPRESSED
  32. extern char *tc_pat_spool;
  33. #endif    /* DOTCOMPRESSED */
  34. char *multibuf=NULL; /* buffer to put the multiple patterns in */
  35. int  multilen = 0; /* length of the multibuf: not the #of multi-patterns! */
  36.  
  37. extern int pos_cnt;    /* to re-initialize it to 0 for reg-exp search */
  38. unsigned Mask[MAXSYM];
  39. unsigned Init1, NO_ERR_MASK, Init[MaxError];
  40. unsigned Bit[WORD+1];
  41. CHAR buffer[BlockSize+Maxline+1];    /* should not be used anywhere: 10/18/93 */
  42. unsigned Next[MaxNext], Next1[MaxNext];
  43. unsigned wildmask, endposition, D_endpos; 
  44. int  LIMITOUTPUT;    /* maximum number of matches we are going to allow */
  45. int  LIMITPERFILE;    /* maximum number of matches per file we are going to allow */
  46. int  LIMITTOTALFILE;    /* maximum number of files we are going to allow */
  47. int  EXITONERROR;    /* return -1 or exit on error? */
  48. int  REGEX, FASTREGEX, RE_ERR, FNAME, WHOLELINE, SIMPLEPATTERN;
  49. int  COUNT, HEAD, TAIL, LINENUM, INVERSE, I, S, DD, AND, SGREP, JUMP; 
  50. int  NOOUTPUTZERO;
  51. int  Num_Pat, PSIZE, prev_num_of_matched, num_of_matched, files_matched, SILENT, NOPROMPT, BESTMATCH, NOUPPER;
  52. int  NOMATCH, TRUNCATE, FIRST_IN_RE, FIRSTOUTPUT;
  53. int  WORDBOUND, DELIMITER, D_length, tc_D_length, original_D_length;
  54. int  EATFIRST, OUTTAIL;
  55. int  BYTECOUNT;
  56. int  PRINTOFFSET;
  57. int  PRINTRECORD;
  58. int  FILEOUT;
  59. int  DNA;
  60. int  APPROX;
  61. int  PAT_FILE;    /* multiple patterns from a given file */
  62. char PAT_FILE_NAME[MAX_LINE_LEN];
  63. int  PAT_BUFFER; /* multiple patterns from a given buffer */
  64. int  CONSTANT;
  65. int  RECURSIVE;
  66. int  total_line; /* used in mgrep */
  67. int  D;
  68. int  M;
  69. int  TCOMPRESSED;
  70. int  EASYSEARCH;    /* 1 used only for compressed files: LITTLE/BIG */
  71. int  ALWAYSFILENAME = OFF;
  72. int  POST_FILTER = OFF;
  73. int  NEW_FILE = OFF;    /* only when post-filter is used */
  74. int  PRINTFILENUMBER = OFF;
  75. int  PRINTPATTERN = OFF;
  76. int  MULTI_OUTPUT = OFF; /* should mgrep print the matched line multiple times for each matched pattern or just once? */
  77. /* invisible to the user, used only by glimpse: cannot use -l since it is incompatible with stdin and -A is used for the index search (done next) */
  78.  
  79. /* Stuff to handle complicated boolean patterns */
  80. int  AComplexBoolean = 0;
  81. ParseTree *AParse = NULL;
  82. int anum_terminals = 0;
  83. ParseTree aterminals[MAXNUM_PAT];
  84. char amatched_terminals[MAXNUM_PAT];
  85.  
  86. #if    MEASURE_TIMES
  87. /* timing variables */
  88. int OUTFILTER_ms;
  89. int FILTERALGO_ms;
  90. int INFILTER_ms;
  91. #endif    /*MEASURE_TIMES*/
  92.  
  93. CHAR **Textfiles = NULL;     /* array of filenames to be searched */
  94. int Numfiles = 0;    /* indicates how many files in Textfiles */
  95. int copied_from_argv = 0; /* were filenames copied from argv (should I free 'em)? */
  96. CHAR old_D_pat[MaxDelimit * 2] = "\n";  /* to hold original D_pattern */
  97. CHAR original_old_D_pat[MaxDelimit * 2] = "\n";
  98. CHAR Pattern[MAXPAT], OldPattern[MAXPAT];
  99. CHAR CurrentFileName[MAX_LINE_LEN];
  100. int SetCurrentFileName = 0;    /* dirty glimpse trick to make filters work: output seems to come from another file */
  101. int CurrentByteOffset;
  102. int SetCurrentByteOffset = 0;
  103. CHAR Progname[MAXNAME]; 
  104. CHAR D_pattern[MaxDelimit * 2] = "\n; "; /* string which delimits records -- defaults to newline */
  105. CHAR tc_D_pattern[MaxDelimit * 2] = "\n";
  106. CHAR original_D_pattern[MaxDelimit * 2] = "\n; ";
  107. char COMP_DIR[MAX_LINE_LEN];
  108. char FREQ_FILE[MAX_LINE_LEN], HASH_FILE[MAX_LINE_LEN], STRING_FILE[MAX_LINE_LEN];    /* interfacing with tcompress */
  109.  
  110. int  NOFILENAME,  /* Boolean flag, set for -h option */
  111.      FILENAMEONLY;/* Boolean flag, set for -l option */
  112. extern int init();
  113. int table[WORD][WORD];
  114. CHAR *agrep_saved_pattern = NULL;    /* to prevent multiple prepfs for each boolean search: crd@hplb.hpl.hp.com */
  115.  
  116. /* Called when multipattern search and pattern has not changed */
  117. void
  118. reinit_value_partial()
  119. {
  120.     num_of_matched = prev_num_of_matched = 0;
  121.     errno = 0;
  122.     FIRST_IN_RE = ON;
  123. }
  124.  
  125. /* This must be called before every agrep_search to reset agrep globals */
  126. void
  127. reinit_value()
  128. {
  129.         int i, j;
  130.  
  131.     /* Added on 7th Oct 194 */
  132.     if (AParse) {
  133.         if (AComplexBoolean) destroy_tree(AParse);
  134.         AComplexBoolean = 0;
  135.         AParse = 0;
  136.         PAT_BUFFER = 0;
  137.         if (multibuf != NULL) free(multibuf);    /* this was allocated for arbit booleans, not multipattern search */
  138.         multibuf = NULL;
  139.         multilen = 0;
  140.         /* Cannot free multifd here since that is always allocated for multipattern search */
  141.     }
  142.     for (i=0; i<anum_terminals; i++) {
  143.         free(aterminals[i].data.leaf.value);
  144.         memset(&aterminals[i], '\0', sizeof(ParseTree));
  145.     }
  146.     anum_terminals = 0;
  147.  
  148.         Bit[WORD] = 1;
  149.         for (i = WORD - 1; i > 0  ; i--)  Bit[i] = Bit[i+1] << 1;
  150.         for (i=0; i< MAXSYM; i++) Mask[i] = 0;
  151.  
  152.         /* bg: new things added on Mar 13 94 */
  153.         Init1 = 0;
  154.         NO_ERR_MASK = 0;
  155.         memset(Init, '\0', MaxError * sizeof(unsigned));
  156.         memset(Next, '\0', MaxNext * sizeof(unsigned));
  157.         memset(Next1, '\0', MaxNext * sizeof(unsigned));
  158.         wildmask = endposition = D_endpos = 0;
  159.         for (i=0; i<WORD; i++)
  160.                 for (j=0; j<WORD; j++)
  161.                         table[i][j] = 0;
  162.  
  163.         strcpy(D_pattern, original_D_pattern);
  164.         D_length = original_D_length;
  165.         strcpy(old_D_pat, original_old_D_pat);
  166.  
  167.     /* Changed on Dec 26th: bg */
  168.     FASTREGEX = REGEX = 0;
  169.     HEAD = TAIL = ON;    /* were off initially */
  170.     RE_ERR = 0;
  171.     AND = 0;
  172.     M = 0;
  173.     pos_cnt = 0;    /* added 31 Jan 95 */
  174.  
  175.     reinit_value_partial();
  176. }
  177.  
  178. /* This must be called before every agrep_init to reset agrep options */
  179. void
  180. initial_value()
  181. {
  182.     SetCurrentFileName = 0;    /* 16/9/94 */
  183.     SetCurrentByteOffset = 0;    /* 23/9/94 */
  184.  
  185.     /* courtesy: crd@hplb.hpl.hp.com */
  186.     if (agrep_saved_pattern) {
  187.         free(agrep_saved_pattern);
  188.         agrep_saved_pattern= NULL;
  189.     }
  190.     /* bg: new stuff on 17/Feb/94 */
  191.     if (multifd != -1) close(multifd);
  192.     multifd = -1;
  193.     if (multibuf != NULL) free(multibuf);
  194.     multibuf = NULL;
  195.     multilen = 0;
  196.     if (pat_spool != NULL) free(pat_spool);
  197.     pat_spool = NULL;
  198. #if    DOTCOMPRESSED
  199.     if (tc_pat_spool != NULL) free(tc_pat_spool);
  200.     tc_pat_spool = NULL;
  201. #endif    /* DOTCOMPRESSED */
  202.     LIMITOUTPUT = 0;    /* means infinity = current semantics */
  203.     LIMITPERFILE = 0;    /* means infinity = current semantics */
  204.     LIMITTOTALFILE = 0;    /* means infinity = current semantics */
  205.     EASYSEARCH = 1;
  206.     DNA = APPROX = PAT_FILE = PAT_BUFFER = CONSTANT = total_line = D = TCOMPRESSED = 0;
  207.     PAT_FILE_NAME[0] = '\0';
  208.     EXITONERROR = NOFILENAME = FILENAMEONLY = FILEOUT = ALWAYSFILENAME = NEW_FILE = POST_FILTER = 0;
  209.  
  210.         original_old_D_pat[0] = old_D_pat[0] = '\n';
  211.         original_old_D_pat[1] = old_D_pat[1] = '\0';
  212.         original_D_pattern[0] = D_pattern[0] = '\n';
  213.         original_D_pattern[1] = D_pattern[1] = ';';
  214.         original_D_pattern[2] = D_pattern[2] = ' ';
  215.         original_D_pattern[3] = D_pattern[3] = '\0';
  216.  
  217.     strcpy(tc_D_pattern, "\n");
  218.     tc_D_length = 1;
  219.  
  220.     /* the functions agrep_init and agrep_search take care of Textfiles and Numfiles */
  221.     agrep_inpointer = 0;
  222.     agrep_outpointer = 0;
  223.     agrep_outlen = 0;
  224. #if    MEASURE_TIMES
  225.     OUTFILTER_ms = FILTERALGO_ms = INFILTER_ms = 0;
  226. #endif    /*MEASURE_TIMES*/
  227.  
  228.     MULTI_OUTPUT = 0;
  229.     PRINTPATTERN = 0;
  230.     PRINTFILENUMBER = 0;
  231.     JUMP = FNAME = BESTMATCH = NOPROMPT = NOUPPER = 0;
  232.     RECURSIVE = 0;
  233.     COUNT = LINENUM = WHOLELINE = SGREP = 0;
  234.     NOOUTPUTZERO = 0;
  235.     EATFIRST = INVERSE = TRUNCATE = OUTTAIL = 0; 
  236.     NOMATCH = FIRSTOUTPUT = ON;    /* were off initally */
  237.     I = DD = S = 1;    /* were off initially */
  238.     original_D_length = D_length = 2;    /* was 0 initially */
  239.     SILENT = Num_Pat = PSIZE = SIMPLEPATTERN = prev_num_of_matched = num_of_matched = files_matched = 0;
  240.     WORDBOUND = DELIMITER = 0;
  241.  
  242.     COMP_DIR[0] = '\0';
  243.     FREQ_FILE[0] = '\0';
  244.     HASH_FILE[0] = '\0';
  245.     STRING_FILE[0] = '\0';
  246.     BYTECOUNT = OFF;
  247.     PRINTOFFSET = OFF;
  248.     PRINTRECORD = ON;
  249.  
  250.     glimpse_clientdied = 0;    /* added 15th Feb 95 */
  251.  
  252.     /* Pattern, OldPattern, execfd, Numfiles are set in agrep_init: so no need to initialize */
  253.     reinit_value();
  254. }
  255.  
  256. void
  257. compute_next(M, Next, Next1)
  258. int M; 
  259. unsigned *Next, *Next1;
  260. {
  261.     int i, j=0, n,  k, temp;
  262.     int mid, pp;
  263.     int MM, base;
  264.     unsigned V[WORD];
  265.  
  266.     base = WORD - M;
  267.     temp = Bit[base]; 
  268.     Bit[base] = 0;
  269.     for (i=0; i<WORD; i++) V[i] = 0;
  270.     for (i=1; i<M; i++)
  271.     {  
  272.         j=0;
  273.         while (table[i][j] > 0 && j < 10) {
  274.             V[i] = V[i] | Bit[base + table[i][j++]];
  275.         }
  276.     }
  277.     Bit[base]=temp;
  278.     if(M <= SHORTREG)
  279.     {
  280.         k = exponen(M);
  281.         pp = 2*k;
  282.         for(i=k; i<pp ; i++)
  283.         {   
  284.             n = i;
  285.             Next[i]= (k>>1);
  286.             for(j=M; j>=1; j--)
  287.             {
  288.                 if(n & Bit[WORD]) Next[i] = Next[i] | V[j];
  289.                 n = (n>>1);
  290.             }
  291.         }      
  292.         return;
  293.     }
  294.     if(M > MAXREG) fprintf(stderr, "%s: regular expression too long\n", Progname);
  295.     MM = M;
  296.     if(M & 1) M=M+1;
  297.     k = exponen(M/2);
  298.     pp = 2*k;
  299.     mid = MM/2;
  300.     for(i=k; i<pp ; i++)
  301.     {     
  302.         n = i;
  303.         Next[i]= (Bit[base]>>1);
  304.         for(j=MM; j>mid ; j--)
  305.         {
  306.             if(n & Bit[WORD]) Next[i] = Next[i] | V[j-mid];
  307.             n = (n>>1);
  308.         }
  309.         n=i-k;
  310.         Next1[i-k] = 0;
  311.         for(j = 0; j<mid; j++)
  312.         {
  313.             if(n & Bit[WORD]) Next1[i-k] = Next1[i-k] | V[MM-j];
  314.             n = (n>>1);
  315.         }
  316.     }      
  317.     return;
  318. }
  319.  
  320. int
  321. exponen(m)
  322. int m;
  323.     int i, ex;
  324.     ex= 1;
  325.     for (i=0; i<m; i++) ex <<= 1;    /* was ex *= 2 */
  326.     return(ex);
  327. }
  328.  
  329. int
  330. re1(Text, M, D)
  331. int Text, M, D;
  332. {
  333.     register unsigned i, c, r0, r1, r2, r3, CMask, Newline, Init0, r_NO_ERR; 
  334.     register unsigned end;
  335.     register unsigned hh, LL=0, k;  /* Lower part */
  336.     int  FIRST_TIME=ON, num_read , j=0, base;
  337.     unsigned A[MaxRerror+1], B[MaxRerror+1];
  338.     unsigned Next[MaxNext], Next1[MaxNext];
  339.     CHAR *buffer;
  340.     int FIRST_LOOP = 1;
  341.  
  342.     r_NO_ERR = NO_ERR_MASK;
  343.     if(M > 30) {
  344.         fprintf(stderr, "%s: regular expression too long\n", Progname);
  345.         if (!EXITONERROR){
  346.             errno = AGREP_ERROR;
  347.             return -1;
  348.         }
  349.         else exit(2);
  350.     }
  351.     base = WORD - M;
  352.     hh = M/2;
  353.     for(i=WORD, j=0; j < hh ; i--, j++) LL = LL | Bit[i];
  354.     if(FIRST_IN_RE) compute_next(M, Next, Next1); 
  355.     /*SUN: try: change to memory allocation */
  356.     FIRST_IN_RE = 0;
  357.     Newline = '\n';
  358.     Init[0] = Bit[base];
  359.     if(HEAD) Init[0] = Init[0] | Bit[base+1];
  360.     for(i=1; i<= D; i++) Init[i] = Init[i-1] | Next[Init[i-1]>>hh] | Next1[Init[i-1]&LL];
  361.     Init1 = Init[0] | 1; 
  362.     Init0 = Init[0];
  363.     r2 = r3 = Init[0];
  364.     for(k=0; k<= D; k++) { 
  365.         A[k] = B[k] = Init[k]; 
  366.     }
  367.  
  368.     if ( D == 0 )
  369.     {
  370. #if    AGREP_POINTER
  371.         if (Text != -1)
  372.         {
  373. #endif    /*AGREP_POINTER*/
  374.         alloc_buf(Text, &buffer, BlockSize+Maxline+1);
  375.         while ((num_read = fill_buf(Text, buffer + Maxline, BlockSize)) > 0)
  376.         {
  377.             i=Maxline; 
  378.             end = num_read + Maxline;
  379.             if((num_read < BlockSize) && buffer[end-1] != '\n') buffer[end] = '\n';
  380.             if(FIRST_LOOP) {         /* if first time in the loop add a newline */
  381.                 buffer[i-1] = '\n';  /* in front the  text.  */
  382.                 i--;
  383.                 CurrentByteOffset --;
  384.                 FIRST_LOOP = 0;
  385.             }
  386.  
  387.             /* RE1_PROCESS_WHEN_DZERO: the while-loop below */
  388.             while ( i < end )
  389.             {
  390.                 c = buffer[i++];
  391.                 CurrentByteOffset ++;
  392.                 CMask = Mask[c];
  393.                 if(c != Newline)
  394.                 {
  395.                     if(CMask != 0) {
  396.                         r1 = Init1 & r3;
  397.                         r2 = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | r1;
  398.                     }
  399.                     else  {
  400.                         r2 = r3 & Init1;
  401.                     }
  402.                 }
  403.                 else {
  404.                     j++;
  405.                     if (DELIMITER) CurrentByteOffset -= D_length;
  406.                     else CurrentByteOffset -= 1;
  407.                     r1 = Init1 & r3;            /* match against endofline */
  408.                     r2 = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | r1;
  409.                     if(TAIL) r2 = (Next[r2>>hh] | Next1[r2&LL]) | r2;                                        /* epsilon move */
  410.                     if(( r2 & 1 ) ^ INVERSE) {
  411.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  412.                             num_of_matched++;
  413.  
  414.                             if (agrep_finalfp != NULL) 
  415.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  416.                             else {
  417.                                 int outindex;
  418.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  419.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  420.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  421.                                 }
  422.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  423.                                     OUTPUT_OVERFLOW;
  424.                                     free_buf(Text, buffer);
  425.                                     return -1;
  426.                                 }
  427.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  428.                                 agrep_outpointer += outindex;
  429.                             }
  430.  
  431.                             free_buf(Text, buffer);
  432.                             NEW_FILE = OFF;
  433.                             return 0;
  434.                         }
  435.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  436.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  437.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  438.                             free_buf(Text, buffer);
  439.                             return 0;    /* done */
  440.                         }
  441.                     }
  442.                     r3 = Init0;
  443.                     r2 = (Next[r3>>hh] | Next1[r3&LL]) & CMask | Init0;
  444.                     /* match begin of line */
  445.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  446.                     else CurrentByteOffset += 1*1;
  447.                 }
  448.                 c = buffer[i++];
  449.                 CurrentByteOffset ++;
  450.                 CMask = Mask[c];
  451.                 if(c != Newline)
  452.                 {
  453.                     if(CMask != 0) {
  454.                         r1 = Init1 & r2;
  455.                         r3 = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  456.                     }
  457.                     else   r3 = r2 & Init1;
  458.                 } /* if(NOT Newline) */
  459.                 else {
  460.                     j++;
  461.                     if (DELIMITER) CurrentByteOffset -= D_length;
  462.                     else CurrentByteOffset -= 1;
  463.                     r1 = Init1 & r2;            /* match against endofline */
  464.                     r3 = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  465.                     if(TAIL) r3 = ( Next[r3>>hh] | Next1[r3&LL] ) | r3;
  466.                     /* epsilon move */
  467.                     if(( r3 & 1 ) ^ INVERSE) {
  468.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  469.                             num_of_matched++;
  470.  
  471.                             if (agrep_finalfp != NULL)
  472.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  473.                             else {
  474.                                 int outindex;
  475.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  476.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  477.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  478.                                 }
  479.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  480.                                     OUTPUT_OVERFLOW;
  481.                                     free_buf(Text, buffer);
  482.                                     return -1;
  483.                                 }
  484.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  485.                                 agrep_outpointer += outindex;
  486.                             }
  487.  
  488.                             free_buf(Text, buffer);
  489.                             NEW_FILE = OFF;
  490.                             return 0;
  491.                         }
  492.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  493.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  494.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  495.                             free_buf(Text, buffer);
  496.                             return 0;    /* done */
  497.                         }
  498.                     }
  499.                     r2 = Init0;
  500.                     r3 = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | Init0;
  501.                     /* match begin of line */
  502.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  503.                     else CurrentByteOffset += 1*1;
  504.                 }
  505.             } /* while i < end ... */
  506.  
  507.             strncpy(buffer, buffer+num_read, Maxline);
  508.         } /* end while fill_buf()... */
  509.  
  510.         free_buf(Text, buffer);
  511.         return 0;
  512. #if    AGREP_POINTER
  513.         }
  514.         else {    /* within the memory buffer: assume it starts with a newline at position 0, the actual pattern follows that, and it ends with a '\n' */
  515.         num_read = agrep_inlen;
  516.         buffer = (CHAR *)agrep_inbuffer;
  517.         end = num_read;
  518.         /* buffer[end-1] = '\n';*/ /* at end of the text. */
  519.         /* buffer[0] = '\n';*/  /* in front of the  text. */
  520.         i = 0;
  521.  
  522.             /* An exact copy of the above RE1_PROCESS_WHEN_DZERO: the while-loop below */
  523.             while ( i < end )
  524.             {
  525.                 c = buffer[i++];
  526.                 CurrentByteOffset ++;
  527.                 CMask = Mask[c];
  528.                 if(c != Newline)
  529.                 {
  530.                     if(CMask != 0) {
  531.                         r1 = Init1 & r3;
  532.                         r2 = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | r1;
  533.                     }
  534.                     else  {
  535.                         r2 = r3 & Init1;
  536.                     }
  537.                 }
  538.                 else {
  539.                     j++;
  540.                     if (DELIMITER) CurrentByteOffset -= D_length;
  541.                     else CurrentByteOffset -= 1;
  542.                     r1 = Init1 & r3;            /* match against endofline */
  543.                     r2 = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | r1;
  544.                     if(TAIL) r2 = (Next[r2>>hh] | Next1[r2&LL]) | r2;                                        /* epsilon move */
  545.                     if(( r2 & 1 ) ^ INVERSE) {
  546.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  547.                             num_of_matched++;
  548.  
  549.                             if (agrep_finalfp != NULL) 
  550.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  551.                             else {
  552.                                 int outindex;
  553.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  554.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  555.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  556.                                 }
  557.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  558.                                     OUTPUT_OVERFLOW;
  559.                                     free_buf(Text, buffer);
  560.                                     return -1;
  561.                                 }
  562.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  563.                                 agrep_outpointer += outindex;
  564.                             }
  565.  
  566.                             free_buf(Text, buffer);
  567.                             NEW_FILE = OFF;
  568.                             return 0;
  569.                         }
  570.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  571.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  572.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  573.                             free_buf(Text, buffer);
  574.                             return 0;    /* done */
  575.                         }
  576.                     }
  577.                     r3 = Init0;
  578.                     r2 = (Next[r3>>hh] | Next1[r3&LL]) & CMask | Init0;
  579.                     /* match begin of line */
  580.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  581.                     else CurrentByteOffset += 1*1;
  582.                 }
  583.                 c = buffer[i++];
  584.                 CurrentByteOffset ++;
  585.                 CMask = Mask[c];
  586.                 if(c != Newline)
  587.                 {
  588.                     if(CMask != 0) {
  589.                         r1 = Init1 & r2;
  590.                         r3 = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  591.                     }
  592.                     else   r3 = r2 & Init1;
  593.                 } /* if(NOT Newline) */
  594.                 else {
  595.                     j++;
  596.                     if (DELIMITER) CurrentByteOffset -= D_length;
  597.                     else CurrentByteOffset -= 1;
  598.                     r1 = Init1 & r2;            /* match against endofline */
  599.                     r3 = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  600.                     if(TAIL) r3 = ( Next[r3>>hh] | Next1[r3&LL] ) | r3;
  601.                     /* epsilon move */
  602.                     if(( r3 & 1 ) ^ INVERSE) {
  603.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  604.                             num_of_matched++;
  605.  
  606.                             if (agrep_finalfp != NULL)
  607.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  608.                             else {
  609.                                 int outindex;
  610.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  611.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  612.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  613.                                 }
  614.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  615.                                     OUTPUT_OVERFLOW;
  616.                                     free_buf(Text, buffer);
  617.                                     return -1;
  618.                                 }
  619.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  620.                                 agrep_outpointer += outindex;
  621.                             }
  622.  
  623.                             free_buf(Text, buffer);
  624.                             NEW_FILE = OFF;
  625.                             return 0;
  626.                         }
  627.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  628.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  629.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  630.                             free_buf(Text, buffer);
  631.                             return 0;    /* done */
  632.                         }
  633.                     }
  634.                     r2 = Init0;
  635.                     r3 = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | Init0;
  636.                     /* match begin of line */
  637.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  638.                     else CurrentByteOffset += 1*1;
  639.                 }
  640.             } /* while i < end ... */
  641.  
  642.         return 0;
  643.         }
  644. #endif    /*AGREP_POINTER*/
  645.     } /*  end if (D == 0) */
  646.  
  647. #if    AGREP_POINTER
  648.     if (Text != -1)
  649.     {
  650. #endif    /*AGREP_POINTER*/
  651.         while ((num_read = fill_buf(Text, buffer + Maxline, BlockSize)) > 0)
  652.         {
  653.             i=Maxline; 
  654.             end = Maxline + num_read;
  655.             if((num_read < BlockSize) && buffer[end-1] != '\n') buffer[end] = '\n';
  656.             if(FIRST_TIME) {         /* if first time in the loop add a newline */
  657.                 buffer[i-1] = '\n';  /* in front the  text.  */
  658.                 i--;
  659.                 CurrentByteOffset --;
  660.                 FIRST_TIME = 0;
  661.             }
  662.  
  663.             /* RE1_PROCESS_WHEN_DNOTZERO: the while loop below */
  664.             while (i < end )
  665.             {
  666.                 c = buffer[i];
  667.                 CMask = Mask[c];
  668.                 if(c !=  Newline)
  669.                 {
  670.                     if(CMask != 0) {  
  671.                         r2 = B[0];
  672.                         r1 = Init1 & r2;
  673.                         A[0] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  674.                         r3 = B[1];
  675.                         r1 = Init1 & r3;
  676.                         r0 = r2 | A[0];     /* A[0] | B[0] */
  677.                         A[1] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | (( r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  678.                         if(D == 1) goto Nextcharfile;
  679.                         r2 = B[2];
  680.                         r1 = Init1 & r2;
  681.                         r0 = r3 | A[1];
  682.                         A[2] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  683.                         if(D == 2) goto Nextcharfile;
  684.                         r3 = B[3];
  685.                         r1 = Init1 & r3;
  686.                         r0 = r2 | A[2];
  687.                         A[3] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  688.                         if(D == 3) goto Nextcharfile;
  689.                         r2 = B[4];
  690.                         r1 = Init1 & r2;
  691.                         r0 = r3 | A[3];
  692.                         A[4] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  693.                         if(D == 4)  goto Nextcharfile;
  694.                     }  /* if(CMask) */
  695.                     else  {
  696.                         r2 = B[0];
  697.                         A[0] = r2 & Init1; 
  698.                         r3 = B[1];
  699.                         r1 = Init1 & r3;
  700.                         r0 = r2 | A[0];
  701.                         A[1] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  702.                         if(D == 1) goto Nextcharfile;
  703.                         r2 = B[2];
  704.                         r1 = Init1 & r2;
  705.                         r0 = r3 | A[1];
  706.                         A[2] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  707.                         if(D == 2) goto Nextcharfile;
  708.                         r3 = B[3];
  709.                         r1 = Init1 & r3;
  710.                         r0 = r2 | A[2];
  711.                         A[3] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  712.                         if(D == 3) goto Nextcharfile;
  713.                         r2 = B[4];
  714.                         r1 = Init1 & r2;
  715.                         r0 = r3 | A[3];
  716.                         A[4] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  717.                         if(D == 4) goto Nextcharfile;
  718.                     }
  719.                 }
  720.                 else {  
  721.                     j++;
  722.                     if (DELIMITER) CurrentByteOffset -= D_length;
  723.                     else CurrentByteOffset -= 1;
  724.                     r1 = Init1 & B[D];            /* match against endofline */
  725.                     A[D] = ((Next[B[D]>>hh] | Next1[B[D]&LL]) & CMask) | r1;
  726.                     if(TAIL) A[D] = ( Next[A[D]>>hh] | Next1[A[D]&LL] ) | A[D]; 
  727.                     /* epsilon move */
  728.                     if(( A[D] & 1 ) ^ INVERSE) {
  729.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  730.                             num_of_matched++;
  731.  
  732.                             if (agrep_finalfp != NULL) 
  733.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  734.                             else {
  735.                                 int outindex;
  736.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  737.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  738.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  739.                                 }
  740.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  741.                                     OUTPUT_OVERFLOW;
  742.                                     free_buf(Text, buffer);
  743.                                     return -1;
  744.                                 }
  745.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  746.                                 agrep_outpointer += outindex;
  747.                             }
  748.  
  749.                             free_buf(Text, buffer);
  750.                             NEW_FILE = OFF;
  751.                             return 0;
  752.                         } 
  753.                         if (-1 == r_output(buffer, i, end, j)) {free_buf(Text, buffer); return -1;}
  754.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  755.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  756.                             free_buf(Text, buffer);
  757.                             return 0;    /* done */
  758.                         }
  759.                     }
  760.                     for(k=0; k<=D; k++)  B[k] = Init[0];
  761.                     r1 = Init1 & B[0];
  762.                     A[0] = (( Next[B[0]>>hh] | Next1[B[0]&LL]) & CMask) | r1;
  763.                     for(k=1; k<=D; k++) {
  764.                         r3 = B[k];
  765.                         r1 = Init1 & r3;
  766.                         r2 = A[k-1] | B[k-1];
  767.                         A[k] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((B[k-1] | Next[r2>>hh] | Next1[r2&LL]) & r_NO_ERR) | r1;
  768.                     }
  769.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  770.                     else CurrentByteOffset += 1*1;
  771.                 }
  772.     Nextcharfile: 
  773.                 i=i+1;
  774.                 CurrentByteOffset ++;
  775.                 c = buffer[i];
  776.                 CMask = Mask[c];
  777.                 if(c != Newline)
  778.                 {
  779.                     if(CMask != 0) {  
  780.                         r2 = A[0];
  781.                         r1 = Init1 & r2;
  782.                         B[0] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  783.                         r3 = A[1];
  784.                         r1 = Init1 & r3;
  785.                         r0 = B[0] | r2;
  786.                         B[1] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((r2 | Next[r0>>hh] | Next1[r0&LL]) & r_NO_ERR) | r1 ;  
  787.                         if(D == 1) goto Nextchar1file;
  788.                         r2 = A[2];
  789.                         r1 = Init1 & r2;
  790.                         r0 = B[1] | r3;
  791.                         B[2] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  792.                         if(D == 2) goto Nextchar1file;
  793.                         r3 = A[3];
  794.                         r1 = Init1 & r3;
  795.                         r0 = B[2] | r2;
  796.                         B[3] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  797.                         if(D == 3) goto Nextchar1file;
  798.                         r2 = A[4];
  799.                         r1 = Init1 & r2;
  800.                         r0 = B[3] | r3;
  801.                         B[4] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  802.                         if(D == 4)   goto Nextchar1file;
  803.                     }  /* if(CMask) */
  804.                     else  {
  805.                         r2 = A[0];
  806.                         B[0] = r2 & Init1; 
  807.                         r3 = A[1];
  808.                         r1 = Init1 & r3;
  809.                         r0 = B[0] | r2;
  810.                         B[1] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  811.                         if(D == 1) goto Nextchar1file;
  812.                         r2 = A[2];
  813.                         r1 = Init1 & r2;
  814.                         r0 = B[1] | r3;
  815.                         B[2] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  816.                         if(D == 2) goto Nextchar1file;
  817.                         r3 = A[3];
  818.                         r1 = Init1 & r3;
  819.                         r0 = B[2] | r2;
  820.                         B[3] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  821.                         if(D == 3) goto Nextchar1file;
  822.                         r2 = A[4];
  823.                         r1 = Init1 & r2;
  824.                         r0 = B[3] | r3;
  825.                         B[4] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  826.                         if(D == 4) goto Nextchar1file;
  827.                     }
  828.                 } /* if(NOT Newline) */
  829.                 else {  
  830.                     j++;
  831.                     if (DELIMITER) CurrentByteOffset -= D_length;
  832.                     else CurrentByteOffset -= 1;
  833.                     r1 = Init1 & A[D];            /* match against endofline */
  834.                     B[D] = ((Next[A[D]>>hh] | Next1[A[D]&LL]) & CMask) | r1;
  835.                     if(TAIL) B[D] = ( Next[B[D]>>hh] | Next1[B[D]&LL] ) | B[D]; 
  836.                     /* epsilon move */
  837.                     if(( B[D] & 1 ) ^ INVERSE) {
  838.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  839.                             num_of_matched++;
  840.  
  841.                             if (agrep_finalfp != NULL) 
  842.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  843.                             else {
  844.                                 int outindex;
  845.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  846.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  847.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  848.                                 }
  849.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  850.                                     OUTPUT_OVERFLOW;
  851.                                     free_buf(Text, buffer);
  852.                                     return -1;
  853.                                 }
  854.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  855.                                 agrep_outpointer += outindex;
  856.                             }
  857.  
  858.                             free_buf(Text, buffer);
  859.                             NEW_FILE = OFF;
  860.                             return 0;
  861.                         } 
  862.                         if (-1 == r_output(buffer, i, end, j)) {free_buf(Text, buffer); return -1;}
  863.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  864.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  865.                             free_buf(Text, buffer);
  866.                             return 0;    /* done */
  867.                         }
  868.                     }
  869.                     for(k=0; k<=D; k++) A[k] = Init0; 
  870.                     r1 = Init1 & A[0];
  871.                     B[0] = ((Next[A[0]>>hh] | Next1[A[0]&LL]) & CMask) | r1;
  872.                     for(k=1; k<=D; k++) {
  873.                         r3 = A[k];
  874.                         r1 = Init1 & r3;
  875.                         r2 = A[k-1] | B[k-1];
  876.                         B[k] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((A[k-1] | Next[r2>>hh] | Next1[r2&LL]) & r_NO_ERR) | r1;
  877.                     }
  878.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  879.                     else CurrentByteOffset += 1*1;
  880.                 }
  881.     Nextchar1file: 
  882.                 i=i+1;
  883.                 CurrentByteOffset ++;
  884.             } /* while i < end */
  885.  
  886.             strncpy(buffer, buffer+num_read, Maxline);
  887.         } /* while fill_buf... */
  888.         free_buf(Text, buffer);
  889.         return 0;
  890. #if    AGREP_POINTER
  891.     }
  892.     else {    /* within the memory buffer: assume it starts with a newline at position 0, the actual pattern follows that, and it ends with a '\n' */
  893.         num_read = agrep_inlen;
  894.         buffer = (CHAR *)agrep_inbuffer;
  895.         end = num_read;
  896.         /* buffer[end-1] = '\n';*/ /* at end of the text. */
  897.         /* buffer[0] = '\n';*/  /* in front of the  text. */
  898.         i = 0;
  899.  
  900.             /* An exact copy of the above RE1_PROCESS_WHEN_DNOTZERO: the while loop below */
  901.             while (i < end )
  902.             {
  903.                 c = buffer[i];
  904.                 CMask = Mask[c];
  905.                 if(c !=  Newline)
  906.                 {
  907.                     if(CMask != 0) {  
  908.                         r2 = B[0];
  909.                         r1 = Init1 & r2;
  910.                         A[0] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  911.                         r3 = B[1];
  912.                         r1 = Init1 & r3;
  913.                         r0 = r2 | A[0];     /* A[0] | B[0] */
  914.                         A[1] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | (( r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  915.                         if(D == 1) goto Nextcharmem;
  916.                         r2 = B[2];
  917.                         r1 = Init1 & r2;
  918.                         r0 = r3 | A[1];
  919.                         A[2] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  920.                         if(D == 2) goto Nextcharmem;
  921.                         r3 = B[3];
  922.                         r1 = Init1 & r3;
  923.                         r0 = r2 | A[2];
  924.                         A[3] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  925.                         if(D == 3) goto Nextcharmem;
  926.                         r2 = B[4];
  927.                         r1 = Init1 & r2;
  928.                         r0 = r3 | A[3];
  929.                         A[4] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  930.                         if(D == 4)  goto Nextcharmem;
  931.                     }  /* if(CMask) */
  932.                     else  {
  933.                         r2 = B[0];
  934.                         A[0] = r2 & Init1; 
  935.                         r3 = B[1];
  936.                         r1 = Init1 & r3;
  937.                         r0 = r2 | A[0];
  938.                         A[1] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  939.                         if(D == 1) goto Nextcharmem;
  940.                         r2 = B[2];
  941.                         r1 = Init1 & r2;
  942.                         r0 = r3 | A[1];
  943.                         A[2] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  944.                         if(D == 2) goto Nextcharmem;
  945.                         r3 = B[3];
  946.                         r1 = Init1 & r3;
  947.                         r0 = r2 | A[2];
  948.                         A[3] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  949.                         if(D == 3) goto Nextcharmem;
  950.                         r2 = B[4];
  951.                         r1 = Init1 & r2;
  952.                         r0 = r3 | A[3];
  953.                         A[4] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  954.                         if(D == 4) goto Nextcharmem;
  955.                     }
  956.                 }
  957.                 else {  
  958.                     j++;
  959.                     if (DELIMITER) CurrentByteOffset -= D_length;
  960.                     else CurrentByteOffset -= 1;
  961.                     r1 = Init1 & B[D];            /* match against endofline */
  962.                     A[D] = ((Next[B[D]>>hh] | Next1[B[D]&LL]) & CMask) | r1;
  963.                     if(TAIL) A[D] = ( Next[A[D]>>hh] | Next1[A[D]&LL] ) | A[D]; 
  964.                     /* epsilon move */
  965.                     if(( A[D] & 1 ) ^ INVERSE) {
  966.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  967.                             num_of_matched++;
  968.  
  969.                             if (agrep_finalfp != NULL) 
  970.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  971.                             else {
  972.                                 int outindex;
  973.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  974.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  975.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  976.                                 }
  977.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  978.                                     OUTPUT_OVERFLOW;
  979.                                     free_buf(Text, buffer);
  980.                                     return -1;
  981.                                 }
  982.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  983.                                 agrep_outpointer += outindex;
  984.                             }
  985.  
  986.                             free_buf(Text, buffer);
  987.                             NEW_FILE = OFF;
  988.                             return 0;
  989.                         } 
  990.                         if (-1 == r_output(buffer, i, end, j)) {free_buf(Text, buffer); return -1;}
  991.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  992.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  993.                             free_buf(Text, buffer);
  994.                             return 0;    /* done */
  995.                         }
  996.                     }
  997.                     for(k=0; k<=D; k++)  B[k] = Init[0];
  998.                     r1 = Init1 & B[0];
  999.                     A[0] = (( Next[B[0]>>hh] | Next1[B[0]&LL]) & CMask) | r1;
  1000.                     for(k=1; k<=D; k++) {
  1001.                         r3 = B[k];
  1002.                         r1 = Init1 & r3;
  1003.                         r2 = A[k-1] | B[k-1];
  1004.                         A[k] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((B[k-1] | Next[r2>>hh] | Next1[r2&LL]) & r_NO_ERR) | r1;
  1005.                     }
  1006.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1007.                     else CurrentByteOffset += 1*1;
  1008.                 }
  1009.     Nextcharmem: 
  1010.                 i=i+1;
  1011.                 CurrentByteOffset ++;
  1012.                 c = buffer[i];
  1013.                 CMask = Mask[c];
  1014.                 if(c != Newline)
  1015.                 {
  1016.                     if(CMask != 0) {  
  1017.                         r2 = A[0];
  1018.                         r1 = Init1 & r2;
  1019.                         B[0] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | r1;
  1020.                         r3 = A[1];
  1021.                         r1 = Init1 & r3;
  1022.                         r0 = B[0] | r2;
  1023.                         B[1] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((r2 | Next[r0>>hh] | Next1[r0&LL]) & r_NO_ERR) | r1 ;  
  1024.                         if(D == 1) goto Nextchar1mem;
  1025.                         r2 = A[2];
  1026.                         r1 = Init1 & r2;
  1027.                         r0 = B[1] | r3;
  1028.                         B[2] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1029.                         if(D == 2) goto Nextchar1mem;
  1030.                         r3 = A[3];
  1031.                         r1 = Init1 & r3;
  1032.                         r0 = B[2] | r2;
  1033.                         B[3] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1034.                         if(D == 3) goto Nextchar1mem;
  1035.                         r2 = A[4];
  1036.                         r1 = Init1 & r2;
  1037.                         r0 = B[3] | r3;
  1038.                         B[4] = ((Next[r2>>hh] | Next1[r2&LL]) & CMask) | ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1039.                         if(D == 4)   goto Nextchar1mem;
  1040.                     }  /* if(CMask) */
  1041.                     else  {
  1042.                         r2 = A[0];
  1043.                         B[0] = r2 & Init1; 
  1044.                         r3 = A[1];
  1045.                         r1 = Init1 & r3;
  1046.                         r0 = B[0] | r2;
  1047.                         B[1] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1048.                         if(D == 1) goto Nextchar1mem;
  1049.                         r2 = A[2];
  1050.                         r1 = Init1 & r2;
  1051.                         r0 = B[1] | r3;
  1052.                         B[2] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1053.                         if(D == 2) goto Nextchar1mem;
  1054.                         r3 = A[3];
  1055.                         r1 = Init1 & r3;
  1056.                         r0 = B[2] | r2;
  1057.                         B[3] = ((r2 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1058.                         if(D == 3) goto Nextchar1mem;
  1059.                         r2 = A[4];
  1060.                         r1 = Init1 & r2;
  1061.                         r0 = B[3] | r3;
  1062.                         B[4] = ((r3 | Next[r0>>hh] | Next1[r0&LL])&r_NO_ERR) | r1 ;  
  1063.                         if(D == 4) goto Nextchar1mem;
  1064.                     }
  1065.                 } /* if(NOT Newline) */
  1066.                 else {  
  1067.                     j++;
  1068.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1069.                     else CurrentByteOffset -= 1;
  1070.                     r1 = Init1 & A[D];            /* match against endofline */
  1071.                     B[D] = ((Next[A[D]>>hh] | Next1[A[D]&LL]) & CMask) | r1;
  1072.                     if(TAIL) B[D] = ( Next[B[D]>>hh] | Next1[B[D]&LL] ) | B[D]; 
  1073.                     /* epsilon move */
  1074.                     if(( B[D] & 1 ) ^ INVERSE) {
  1075.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1076.                             num_of_matched++;
  1077.  
  1078.                             if (agrep_finalfp != NULL) 
  1079.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1080.                             else {
  1081.                                 int outindex;
  1082.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1083.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1084.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1085.                                 }
  1086.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1087.                                     OUTPUT_OVERFLOW;
  1088.                                     free_buf(Text, buffer);
  1089.                                     return -1;
  1090.                                 }
  1091.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1092.                                 agrep_outpointer += outindex;
  1093.                             }
  1094.  
  1095.                             free_buf(Text, buffer);
  1096.                             NEW_FILE = OFF;
  1097.                             return 0;
  1098.                         } 
  1099.                         if (-1 == r_output(buffer, i, end, j)) {free_buf(Text, buffer); return -1;}
  1100.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1101.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1102.                             free_buf(Text, buffer);
  1103.                             return 0;    /* done */
  1104.                         }
  1105.                     }
  1106.                     for(k=0; k<=D; k++) A[k] = Init0; 
  1107.                     r1 = Init1 & A[0];
  1108.                     B[0] = ((Next[A[0]>>hh] | Next1[A[0]&LL]) & CMask) | r1;
  1109.                     for(k=1; k<=D; k++) {
  1110.                         r3 = A[k];
  1111.                         r1 = Init1 & r3;
  1112.                         r2 = A[k-1] | B[k-1];
  1113.                         B[k] = ((Next[r3>>hh] | Next1[r3&LL]) & CMask) | ((A[k-1] | Next[r2>>hh] | Next1[r2&LL]) & r_NO_ERR) | r1;
  1114.                     }
  1115.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1116.                     else CurrentByteOffset += 1*1;
  1117.                 }
  1118.     Nextchar1mem: 
  1119.                 i=i+1;
  1120.                 CurrentByteOffset ++;
  1121.             } /* while i < end */
  1122.  
  1123.         return 0;
  1124.     }
  1125. #endif    /*AGREP_POINTER*/
  1126. } /* re1 */
  1127.  
  1128. int
  1129. re(Text, M, D)
  1130. int Text, M, D;
  1131. {
  1132.     register unsigned i, c, r1, r2, r3, CMask, k, Newline, Init0, Init1, end; 
  1133.     register unsigned r_even, r_odd, r_NO_ERR ;
  1134.     unsigned RMask[MAXSYM];
  1135.     unsigned A[MaxRerror+1], B[MaxRerror+1];
  1136.     int num_read, j=0, lasti, base, ResidueSize; 
  1137.     int FIRST_TIME; /* Flag */
  1138.     CHAR *buffer;
  1139.  
  1140.     base = WORD - M;
  1141.     k = 2*exponen(M);
  1142.     if(FIRST_IN_RE) {
  1143.         compute_next(M, Next, Next1); 
  1144.         FIRST_IN_RE = 0;    
  1145.     }
  1146.     for(i=0; i< MAXSYM; i++) RMask[i] = Mask[i];
  1147.     r_NO_ERR = NO_ERR_MASK;
  1148.     Newline = '\n';
  1149.     Init0 = Init[0] = Bit[base];
  1150.     if(HEAD) Init0  = Init[0] = Init0 | Bit[base+1] ;
  1151.     for(i=1; i<= D; i++) Init[i] = Init[i-1] | Next[Init[i-1]]; /* can be out? */
  1152.     Init1 = Init0 | 1; 
  1153.     r2 = r3 = Init0;
  1154.     for(k=0; k<= D; k++) { 
  1155.         A[k] = B[k] = Init[0]; 
  1156.     }  /* can be out? */
  1157.     FIRST_TIME = ON;
  1158.     alloc_buf(Text, &buffer, BlockSize+Maxline+1);
  1159.     if ( D == 0 )
  1160.     {
  1161. #if    AGREP_POINTER
  1162.         if(Text != -1) {
  1163. #endif    /*AGREP_POINTER*/
  1164.         lasti = Maxline;
  1165.         while ((num_read = fill_buf(Text, buffer + Maxline, BlockSize)) > 0)
  1166.         {
  1167.             i=Maxline; 
  1168.             end = Maxline + num_read ;
  1169.             if((num_read < BlockSize)&&buffer[end-1] != '\n') buffer[end] = '\n';
  1170.             if(FIRST_TIME) {
  1171.                 buffer[i-1] = '\n';
  1172.                 i--;
  1173.                 CurrentByteOffset --;
  1174.                 FIRST_TIME = 0;
  1175.             }
  1176.  
  1177.             /* RE_PROCESS_WHEN_DZERO: the while-loop below */
  1178.             while (i < end) 
  1179.             {
  1180.                 c = buffer[i++];
  1181.                 CurrentByteOffset ++;
  1182.                 CMask = RMask[c];
  1183.                 if(c != Newline)
  1184.                 {  
  1185.                     r1 = Init1 & r3;
  1186.                     r2 = (Next[r3] & CMask) | r1;
  1187.                 }
  1188.                 else {  
  1189.                     r1 = Init1 & r3;            /* match against '\n' */
  1190.                     r2 = Next[r3] & CMask | r1;
  1191.                     j++;
  1192.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1193.                     else CurrentByteOffset -= 1;
  1194.                     if(TAIL) r2 = Next[r2] | r2 ;   /* epsilon move */
  1195.                     if(( r2 & 1) ^ INVERSE) {
  1196.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1197.                             num_of_matched++;
  1198.  
  1199.                             if (agrep_finalfp != NULL) 
  1200.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1201.                             else {
  1202.                                 int outindex;
  1203.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1204.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1205.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1206.                                 }
  1207.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1208.                                     OUTPUT_OVERFLOW;
  1209.                                     free_buf(Text, buffer);
  1210.                                     return -1;
  1211.                                 }
  1212.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1213.                                 agrep_outpointer += outindex;
  1214.                             }
  1215.  
  1216.                             free_buf(Text, buffer);
  1217.                             NEW_FILE = OFF;
  1218.                             return 0;
  1219.                         } 
  1220.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  1221.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1222.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1223.                             free_buf(Text, buffer);
  1224.                             return 0;    /* done */
  1225.                         }
  1226.                     }
  1227.                     lasti = i - 1;
  1228.                     r3 = Init0;
  1229.                     r2 = (Next[r3] & CMask) | Init0;
  1230.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1231.                     else CurrentByteOffset += 1*1;
  1232.                 }
  1233.                 c = buffer[i++];   
  1234.                 CurrentByteOffset ++;
  1235.                 CMask = RMask[c];
  1236.                 if(c != Newline)
  1237.                 {
  1238.                     r1 = Init1 & r2;
  1239.                     r3 = (Next[r2] & CMask) | r1;
  1240.                 }
  1241.                 else {  
  1242.                     j++;
  1243.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1244.                     else CurrentByteOffset -= 1;
  1245.                     r1 = Init1 & r2;            /* match against endofline */
  1246.                     r3 = Next[r2] & CMask | r1;
  1247.                     if(TAIL) r3 = Next[r3] | r3;
  1248.                     if(( r3 & 1) ^ INVERSE) {
  1249.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1250.                             num_of_matched++;
  1251.  
  1252.                             if (agrep_finalfp != NULL) 
  1253.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1254.                             else {
  1255.                                 int outindex;
  1256.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1257.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1258.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1259.                                 }
  1260.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1261.                                     OUTPUT_OVERFLOW;
  1262.                                     free_buf(Text, buffer);
  1263.                                     return -1;
  1264.                                 }
  1265.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1266.                                 agrep_outpointer += outindex;
  1267.                             }
  1268.  
  1269.                             free_buf(Text, buffer);
  1270.                             NEW_FILE = OFF;
  1271.                             return 0;
  1272.                         } 
  1273.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  1274.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1275.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1276.                             free_buf(Text, buffer);
  1277.                             return 0;    /* done */
  1278.                         }
  1279.                     }
  1280.                     lasti = i - 1;
  1281.                     r2 = Init0; 
  1282.                     r3 = (Next[r2] & CMask) | Init0;  /* match the newline */
  1283.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1284.                     else CurrentByteOffset += 1*1;
  1285.                 }
  1286.             } /* while */
  1287.  
  1288.             ResidueSize = Maxline + num_read - lasti;
  1289.             if(ResidueSize > Maxline) {
  1290.                 ResidueSize = Maxline;  
  1291.             }
  1292.             strncpy(buffer+Maxline-ResidueSize, buffer+lasti, ResidueSize);
  1293.             lasti = Maxline - ResidueSize;
  1294.         } /* while fill_buf() */
  1295.         free_buf(Text, buffer);
  1296.         return 0;
  1297. #if    AGREP_POINTER
  1298.         }
  1299.         else {
  1300.         num_read = agrep_inlen;
  1301.         buffer = (CHAR *)agrep_inbuffer;
  1302.         end = num_read;
  1303.         /* buffer[end-1] = '\n';*/ /* at end of the text. */
  1304.         /* buffer[0] = '\n';*/  /* in front of the  text. */
  1305.         i = 0;
  1306.         lasti = 1;
  1307.  
  1308.             /* An exact copy of the above RE_PROCESS_WHEN_DZERO: the while-loop below */
  1309.             while (i < end) 
  1310.             {
  1311.                 c = buffer[i++];
  1312.                 CurrentByteOffset ++;
  1313.                 CMask = RMask[c];
  1314.                 if(c != Newline)
  1315.                 {  
  1316.                     r1 = Init1 & r3;
  1317.                     r2 = (Next[r3] & CMask) | r1;
  1318.                 }
  1319.                 else {  
  1320.                     r1 = Init1 & r3;            /* match against '\n' */
  1321.                     r2 = Next[r3] & CMask | r1;
  1322.                     j++;
  1323.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1324.                     else CurrentByteOffset -= 1;
  1325.                     if(TAIL) r2 = Next[r2] | r2 ;   /* epsilon move */
  1326.                     if(( r2 & 1) ^ INVERSE) {
  1327.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1328.                             num_of_matched++;
  1329.  
  1330.                             if (agrep_finalfp != NULL) 
  1331.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1332.                             else {
  1333.                                 int outindex;
  1334.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1335.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1336.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1337.                                 }
  1338.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1339.                                     OUTPUT_OVERFLOW;
  1340.                                     free_buf(Text, buffer);
  1341.                                     return -1;
  1342.                                 }
  1343.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1344.                                 agrep_outpointer += outindex;
  1345.                             }
  1346.  
  1347.                             free_buf(Text, buffer);
  1348.                             NEW_FILE = OFF;
  1349.                             return 0;
  1350.                         } 
  1351.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  1352.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1353.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1354.                             free_buf(Text, buffer);
  1355.                             return 0;    /* done */
  1356.                         }
  1357.                     }
  1358.                     lasti = i - 1;
  1359.                     r3 = Init0;
  1360.                     r2 = (Next[r3] & CMask) | Init0;
  1361.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1362.                     else CurrentByteOffset += 1*1;
  1363.                 }
  1364.                 c = buffer[i++];   
  1365.                 CurrentByteOffset ++;
  1366.                 CMask = RMask[c];
  1367.                 if(c != Newline)
  1368.                 {
  1369.                     r1 = Init1 & r2;
  1370.                     r3 = (Next[r2] & CMask) | r1;
  1371.                 }
  1372.                 else {  
  1373.                     j++;
  1374.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1375.                     else CurrentByteOffset -= 1;
  1376.                     r1 = Init1 & r2;            /* match against endofline */
  1377.                     r3 = Next[r2] & CMask | r1;
  1378.                     if(TAIL) r3 = Next[r3] | r3;
  1379.                     if(( r3 & 1) ^ INVERSE) {
  1380.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1381.                             num_of_matched++;
  1382.  
  1383.                             if (agrep_finalfp != NULL) 
  1384.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1385.                             else {
  1386.                                 int outindex;
  1387.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1388.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1389.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1390.                                 }
  1391.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1392.                                     OUTPUT_OVERFLOW;
  1393.                                     free_buf(Text, buffer);
  1394.                                     return -1;
  1395.                                 }
  1396.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1397.                                 agrep_outpointer += outindex;
  1398.                             }
  1399.  
  1400.                             free_buf(Text, buffer);
  1401.                             NEW_FILE = OFF;
  1402.                             return 0;
  1403.                         } 
  1404.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  1405.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1406.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1407.                             free_buf(Text, buffer);
  1408.                             return 0;    /* done */
  1409.                         }
  1410.                     }
  1411.                     lasti = i - 1;
  1412.                     r2 = Init0; 
  1413.                     r3 = (Next[r2] & CMask) | Init0;  /* match the newline */
  1414.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1415.                     else CurrentByteOffset += 1*1;
  1416.                 }
  1417.             } /* while */
  1418.  
  1419.         /* If a residue is left for within-memory-buffer, since nothing can be "read" after that, we can ignore it: as if only 1 iteration of while */
  1420.         return 0;
  1421.         }
  1422. #endif    /*AGREP_POINTER*/
  1423.     } /* end if(D==0) */
  1424.  
  1425. #if    AGREP_POINTER
  1426.     if (Text != -1) {
  1427. #endif    /*AGREP_POINTER*/
  1428.         while ((num_read = fill_buf(Text, buffer + Maxline, BlockSize)) > 0)
  1429.         {
  1430.             i=Maxline; 
  1431.             end = Maxline+num_read;
  1432.             if((num_read < BlockSize) && buffer[end-1] != '\n') buffer[end] = '\n';
  1433.             if(FIRST_TIME) {
  1434.                 buffer[i-1] = '\n';
  1435.                 i--;
  1436.                 CurrentByteOffset --;
  1437.                 FIRST_TIME = 0;
  1438.             }
  1439.  
  1440.             /* RE_PROCESS_WHEN_DNOTZERO: the while-loop below */
  1441.             while (i < end)
  1442.             {   
  1443.                 c = buffer[i++];
  1444.                 CurrentByteOffset ++;
  1445.                 CMask = RMask[c];
  1446.                 if (c != Newline)
  1447.                 {  
  1448.                     r_even = B[0];
  1449.                     r1 = Init1 & r_even;
  1450.                     A[0] = (Next[r_even] & CMask) | r1;
  1451.                     r_odd = B[1];
  1452.                     r1 = Init1 & r_odd;
  1453.                     r2 = (r_even | Next[r_even|A[0]]) &r_NO_ERR;
  1454.                     A[1] = (Next[r_odd] & CMask) | r2 | r1 ;  
  1455.                     if(D == 1) goto Nextcharfile;
  1456.                     r_even = B[2];
  1457.                     r1 = Init1 & r_even;
  1458.                     r2 = (r_odd | Next[r_odd|A[1]]) &r_NO_ERR;
  1459.                     A[2] = (Next[r_even] & CMask) | r2 | r1 ;  
  1460.                     if(D == 2) goto Nextcharfile;
  1461.                     r_odd = B[3];
  1462.                     r1 = Init1 & r_odd;
  1463.                     r2 = (r_even | Next[r_even|A[2]]) &r_NO_ERR;
  1464.                     A[3] = (Next[r_odd] & CMask) | r2 | r1 ;  
  1465.                     if(D == 3) goto Nextcharfile;
  1466.                     r_even = B[4];
  1467.                     r1 = Init1 & r_even;
  1468.                     r2 = (r_odd | Next[r_odd|A[3]]) &r_NO_ERR;
  1469.                     A[4] = (Next[r_even] & CMask) | r2 | r1 ;  
  1470.                     goto Nextcharfile;
  1471.                 } /* if NOT Newline */
  1472.                 else {  
  1473.                     j++;
  1474.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1475.                     else CurrentByteOffset -= 1;
  1476.                     r1 = Init1 & B[D];               /* match endofline */
  1477.                     A[D] = (Next[B[D]] & CMask) | r1;
  1478.                     if(TAIL) A[D] = Next[A[D]] | A[D];
  1479.                     if((A[D] & 1) ^ INVERSE )  {
  1480.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1481.                             num_of_matched++;    
  1482.  
  1483.                             if (agrep_finalfp != NULL) 
  1484.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1485.                             else {
  1486.                                 int outindex;
  1487.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1488.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1489.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1490.                                 }
  1491.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1492.                                     OUTPUT_OVERFLOW;
  1493.                                     free_buf(Text, buffer);
  1494.                                     return -1;
  1495.                                 }
  1496.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1497.                                 agrep_outpointer += outindex;
  1498.                             }
  1499.  
  1500.                             free_buf(Text, buffer);
  1501.                             NEW_FILE = OFF;
  1502.                             return 0;
  1503.                         }  
  1504.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  1505.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1506.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1507.                             free_buf(Text, buffer);
  1508.                             return 0;    /* done */
  1509.                         }
  1510.                     }
  1511.                     for(k=0; k<= D; k++) { 
  1512.                         A[k] = B[k] = Init[k]; 
  1513.                     }
  1514.                     r1 = Init1 & B[0]; 
  1515.                     A[0] = (Next[B[0]] & CMask) | r1;
  1516.                     for(k=1; k<= D; k++) {
  1517.                         r1 = Init1 & B[k];
  1518.                         r2 = (B[k-1] | Next[A[k-1]|B[k-1]]) &r_NO_ERR;
  1519.                         A[k] = (Next[B[k]] & CMask) | r1 | r2;
  1520.                     }
  1521.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1522.                     else CurrentByteOffset += 1*1;
  1523.                 }
  1524.     Nextcharfile: 
  1525.                 c = buffer[i];
  1526.                 CMask = RMask[c];
  1527.                 if(c != Newline)
  1528.                 { 
  1529.                     r1 = Init1 & A[0];
  1530.                     B[0] = (Next[A[0]] & CMask) | r1;
  1531.                     r1 = Init1 & A[1];
  1532.                     B[1] = (Next[A[1]] & CMask) | ((A[0] | Next[A[0] | B[0]]) & r_NO_ERR) | r1 ;  
  1533.                     if(D == 1) goto Nextchar1file;
  1534.                     r1 = Init1 & A[2];
  1535.                     B[2] = (Next[A[2]] & CMask) | ((A[1] | Next[A[1] | B[1]]) &r_NO_ERR) | r1 ;  
  1536.                     if(D == 2) goto Nextchar1file;
  1537.                     r1 = Init1 & A[3];
  1538.                     B[3] = (Next[A[3]] & CMask) | ((A[2] | Next[A[2] | B[2]])&r_NO_ERR) | r1 ;  
  1539.                     if(D == 3) goto Nextchar1file;
  1540.                     r1 = Init1 & A[4];
  1541.                     B[4] = (Next[A[4]] & CMask) | ((A[3] | Next[A[3] | B[3]])&r_NO_ERR) | r1 ;  
  1542.                     goto Nextchar1file;
  1543.                 } /* if(NOT Newline) */
  1544.                 else {  
  1545.                     j++;
  1546.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1547.                     else CurrentByteOffset -= 1;
  1548.                     r1 = Init1 & A[D];               /* match endofline */
  1549.                     B[D] = (Next[A[D]] & CMask) | r1;
  1550.                     if(TAIL) B[D] = Next[B[D]] | B[D];
  1551.                     if((B[D] & 1) ^ INVERSE )  {
  1552.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1553.                             num_of_matched++;
  1554.  
  1555.                             if (agrep_finalfp != NULL) 
  1556.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1557.                             else {
  1558.                                 int outindex;
  1559.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1560.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1561.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1562.                                 }
  1563.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1564.                                     OUTPUT_OVERFLOW;
  1565.                                     free_buf(Text, buffer);
  1566.                                     return -1;
  1567.                                 }
  1568.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1569.                                 agrep_outpointer += outindex;
  1570.                             }
  1571.  
  1572.                             free_buf(Text, buffer);
  1573.                             NEW_FILE = OFF;
  1574.                             return 0;
  1575.                         } 
  1576.                         if (-1 == r_output(buffer, i, end, j)) {free_buf(Text, buffer); return -1;}
  1577.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1578.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1579.                             free_buf(Text, buffer);
  1580.                             return 0;    /* done */
  1581.                         }
  1582.                     }
  1583.                     for(k=0; k<= D; k++) { 
  1584.                         A[k] = B[k] = Init[k]; 
  1585.                     }
  1586.                     r1 = Init1 & A[0]; 
  1587.                     B[0] = (Next[A[0]] & CMask) | r1;
  1588.                     for(k=1; k<= D; k++) {
  1589.                         r1 = Init1 & A[k];
  1590.                         r2 = (A[k-1] | Next[A[k-1]|B[k-1]])&r_NO_ERR;
  1591.                         B[k] = (Next[A[k]] & CMask) | r1 | r2;
  1592.                     }
  1593.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1594.                     else CurrentByteOffset += 1*1;
  1595.                 }
  1596.     Nextchar1file: 
  1597.                 i++;
  1598.                 CurrentByteOffset ++;
  1599.             } /* while i < end */
  1600.  
  1601.             strncpy(buffer, buffer+num_read, Maxline);
  1602.         } /* while  fill_buf() */
  1603.         free_buf(Text, buffer);
  1604.         return 0;
  1605. #if    AGREP_POINTER
  1606.     }
  1607.     else {
  1608.         num_read = agrep_inlen;
  1609.         buffer = (CHAR *)agrep_inbuffer;
  1610.         end = num_read;
  1611.         /* buffer[end-1] = '\n';*/ /* at end of the text. */
  1612.         /* buffer[0] = '\n';*/  /* in front of the  text. */
  1613.         i = 0;
  1614.  
  1615.             /* An exact copy of the above RE_PROCESS_WHEN_DNOTZERO: the while-loop below */
  1616.             while (i < end)
  1617.             {   
  1618.                 c = buffer[i++];
  1619.                 CurrentByteOffset ++;
  1620.                 CMask = RMask[c];
  1621.                 if (c != Newline)
  1622.                 {  
  1623.                     r_even = B[0];
  1624.                     r1 = Init1 & r_even;
  1625.                     A[0] = (Next[r_even] & CMask) | r1;
  1626.                     r_odd = B[1];
  1627.                     r1 = Init1 & r_odd;
  1628.                     r2 = (r_even | Next[r_even|A[0]]) &r_NO_ERR;
  1629.                     A[1] = (Next[r_odd] & CMask) | r2 | r1 ;  
  1630.                     if(D == 1) goto Nextcharmem;
  1631.                     r_even = B[2];
  1632.                     r1 = Init1 & r_even;
  1633.                     r2 = (r_odd | Next[r_odd|A[1]]) &r_NO_ERR;
  1634.                     A[2] = (Next[r_even] & CMask) | r2 | r1 ;  
  1635.                     if(D == 2) goto Nextcharmem;
  1636.                     r_odd = B[3];
  1637.                     r1 = Init1 & r_odd;
  1638.                     r2 = (r_even | Next[r_even|A[2]]) &r_NO_ERR;
  1639.                     A[3] = (Next[r_odd] & CMask) | r2 | r1 ;  
  1640.                     if(D == 3) goto Nextcharmem;
  1641.                     r_even = B[4];
  1642.                     r1 = Init1 & r_even;
  1643.                     r2 = (r_odd | Next[r_odd|A[3]]) &r_NO_ERR;
  1644.                     A[4] = (Next[r_even] & CMask) | r2 | r1 ;  
  1645.                     goto Nextcharmem;
  1646.                 } /* if NOT Newline */
  1647.                 else {  
  1648.                     j++;
  1649.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1650.                     else CurrentByteOffset -= 1;
  1651.                     r1 = Init1 & B[D];               /* match endofline */
  1652.                     A[D] = (Next[B[D]] & CMask) | r1;
  1653.                     if(TAIL) A[D] = Next[A[D]] | A[D];
  1654.                     if((A[D] & 1) ^ INVERSE )  {
  1655.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1656.                             num_of_matched++;    
  1657.  
  1658.                             if (agrep_finalfp != NULL) 
  1659.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1660.                             else {
  1661.                                 int outindex;
  1662.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1663.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1664.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1665.                                 }
  1666.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1667.                                     OUTPUT_OVERFLOW;
  1668.                                     free_buf(Text, buffer);
  1669.                                     return -1;
  1670.                                 }
  1671.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1672.                                 agrep_outpointer += outindex;
  1673.                             }
  1674.  
  1675.                             free_buf(Text, buffer);
  1676.                             NEW_FILE = OFF;
  1677.                             return 0;
  1678.                         }  
  1679.                         if (-1 == r_output(buffer, i-1, end, j)) {free_buf(Text, buffer); return -1;}
  1680.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1681.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1682.                             free_buf(Text, buffer);
  1683.                             return 0;    /* done */
  1684.                         }
  1685.                     }
  1686.                     for(k=0; k<= D; k++) { 
  1687.                         A[k] = B[k] = Init[k]; 
  1688.                     }
  1689.                     r1 = Init1 & B[0]; 
  1690.                     A[0] = (Next[B[0]] & CMask) | r1;
  1691.                     for(k=1; k<= D; k++) {
  1692.                         r1 = Init1 & B[k];
  1693.                         r2 = (B[k-1] | Next[A[k-1]|B[k-1]]) &r_NO_ERR;
  1694.                         A[k] = (Next[B[k]] & CMask) | r1 | r2;
  1695.                     }
  1696.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1697.                     else CurrentByteOffset += 1*1;
  1698.                 }
  1699.     Nextcharmem: 
  1700.                 c = buffer[i];
  1701.                 CMask = RMask[c];
  1702.                 if(c != Newline)
  1703.                 { 
  1704.                     r1 = Init1 & A[0];
  1705.                     B[0] = (Next[A[0]] & CMask) | r1;
  1706.                     r1 = Init1 & A[1];
  1707.                     B[1] = (Next[A[1]] & CMask) | ((A[0] | Next[A[0] | B[0]]) & r_NO_ERR) | r1 ;  
  1708.                     if(D == 1) goto Nextchar1mem;
  1709.                     r1 = Init1 & A[2];
  1710.                     B[2] = (Next[A[2]] & CMask) | ((A[1] | Next[A[1] | B[1]]) &r_NO_ERR) | r1 ;  
  1711.                     if(D == 2) goto Nextchar1mem;
  1712.                     r1 = Init1 & A[3];
  1713.                     B[3] = (Next[A[3]] & CMask) | ((A[2] | Next[A[2] | B[2]])&r_NO_ERR) | r1 ;  
  1714.                     if(D == 3) goto Nextchar1mem;
  1715.                     r1 = Init1 & A[4];
  1716.                     B[4] = (Next[A[4]] & CMask) | ((A[3] | Next[A[3] | B[3]])&r_NO_ERR) | r1 ;  
  1717.                     goto Nextchar1mem;
  1718.                 } /* if(NOT Newline) */
  1719.                 else {  
  1720.                     j++;
  1721.                     if (DELIMITER) CurrentByteOffset -= D_length;
  1722.                     else CurrentByteOffset -= 1;
  1723.                     r1 = Init1 & A[D];               /* match endofline */
  1724.                     B[D] = (Next[A[D]] & CMask) | r1;
  1725.                     if(TAIL) B[D] = Next[B[D]] | B[D];
  1726.                     if((B[D] & 1) ^ INVERSE )  {
  1727.                         if(FILENAMEONLY && (NEW_FILE || !POST_FILTER)) {
  1728.                             num_of_matched++;
  1729.  
  1730.                             if (agrep_finalfp != NULL) 
  1731.                                 fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  1732.                             else {
  1733.                                 int outindex;
  1734.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) && 
  1735.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  1736.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1737.                                 }
  1738.                                 if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  1739.                                     OUTPUT_OVERFLOW;
  1740.                                     free_buf(Text, buffer);
  1741.                                     return -1;
  1742.                                 }
  1743.                                 else agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  1744.                                 agrep_outpointer += outindex;
  1745.                             }
  1746.  
  1747.                             free_buf(Text, buffer);
  1748.                             NEW_FILE = OFF;
  1749.                             return 0;
  1750.                         } 
  1751.                         if (-1 == r_output(buffer, i, end, j)) {free_buf(Text, buffer); return -1;}
  1752.                         if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  1753.                             ((LIMITPERFILE > 0) && (LIMITPERFILE <= num_of_matched - prev_num_of_matched))) {
  1754.                             free_buf(Text, buffer);
  1755.                             return 0;    /* done */
  1756.                         }
  1757.                     }
  1758.                     for(k=0; k<= D; k++) { 
  1759.                         A[k] = B[k] = Init[k]; 
  1760.                     }
  1761.                     r1 = Init1 & A[0]; 
  1762.                     B[0] = (Next[A[0]] & CMask) | r1;
  1763.                     for(k=1; k<= D; k++) {
  1764.                         r1 = Init1 & A[k];
  1765.                         r2 = (A[k-1] | Next[A[k-1]|B[k-1]])&r_NO_ERR;
  1766.                         B[k] = (Next[A[k]] & CMask) | r1 | r2;
  1767.                     }
  1768.                     if (DELIMITER) CurrentByteOffset += 1*D_length;
  1769.                     else CurrentByteOffset += 1*1;
  1770.                 }
  1771.     Nextchar1mem: 
  1772.                 i++;
  1773.                 CurrentByteOffset ++;
  1774.             } /* while i < end */
  1775.  
  1776.         return 0;
  1777.     }
  1778. #endif    /*AGREP_POINTER*/
  1779. } /* re */
  1780.  
  1781. int
  1782. r_output (buffer, i, end, j) 
  1783. int i, end, j; 
  1784. CHAR *buffer;
  1785. {
  1786.     int PRINTED = 0;
  1787.     int bp;
  1788.     if(i >= end) return 0;
  1789.     if ((j < 1) || (CurrentByteOffset < 0)) return 0;
  1790.     num_of_matched++;
  1791.     if(COUNT)  return 0;
  1792.     if(FNAME && (NEW_FILE || !POST_FILTER)) {
  1793.         char    nextchar = (POST_FILTER == ON)?'\n':' ';
  1794.         char    *prevstring = (POST_FILTER == ON)?"\n":"";
  1795.         if (agrep_finalfp != NULL)
  1796.             fprintf(agrep_finalfp, "%s%s:%c", prevstring, CurrentFileName, nextchar);
  1797.         else {
  1798.             int outindex;
  1799.             if (prevstring[0] != '\0') {
  1800.                 if(agrep_outpointer + 1 >= agrep_outlen) {
  1801.                     OUTPUT_OVERFLOW;
  1802.                     return -1;
  1803.                 }
  1804.                 else agrep_outbuffer[agrep_outpointer ++] = prevstring[0];
  1805.             }
  1806.             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  1807.                     (CurrentFileName[outindex] != '\0'); outindex++) {
  1808.                 agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  1809.             }
  1810.             if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+2>=agrep_outlen)) {
  1811.                 OUTPUT_OVERFLOW;
  1812.                 return -1;
  1813.             }
  1814.             else {
  1815.                 agrep_outbuffer[agrep_outpointer+outindex++] = ':';
  1816.                 agrep_outbuffer[agrep_outpointer+outindex++] = nextchar;
  1817.             }
  1818.             agrep_outpointer += outindex;
  1819.         }
  1820.         NEW_FILE = OFF;
  1821.         PRINTED = 1;
  1822.     }
  1823.     bp = i-1;
  1824.     while ((buffer[bp] != '\n') && (bp > 0)) bp--;
  1825.     if(LINENUM) {
  1826.         if (agrep_finalfp != NULL)
  1827.             fprintf(agrep_finalfp, "%d: ", j-1); 
  1828.         else {
  1829.             char s[32];
  1830.             int  outindex;
  1831.  
  1832.             sprintf(s, "%d: ", j-1);
  1833.             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  1834.                     (s[outindex] != '\0'); outindex++) {
  1835.                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  1836.             }
  1837.             if (s[outindex] != '\0') {
  1838.                 OUTPUT_OVERFLOW;
  1839.                 return -1;
  1840.             }
  1841.             agrep_outpointer += outindex;
  1842.         }
  1843.         PRINTED = 1;
  1844.     }
  1845.  
  1846.     if(BYTECOUNT) {
  1847.         if (agrep_finalfp != NULL)
  1848.             fprintf(agrep_finalfp, "%d= ", CurrentByteOffset);
  1849.         else {
  1850.             char s[32];
  1851.             int  outindex;
  1852.             sprintf(s, "%d= ", CurrentByteOffset);
  1853.             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  1854.                     (s[outindex] != '\0'); outindex++) {
  1855.                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  1856.             }
  1857.             if (s[outindex] != '\0') {
  1858.                 OUTPUT_OVERFLOW;
  1859.                 return -1;
  1860.             }
  1861.             agrep_outpointer += outindex;
  1862.         }
  1863.         PRINTED = 1;
  1864.     }
  1865.  
  1866.     if(buffer[bp] != '\n') bp = Maxline-1;
  1867.     bp++;
  1868.  
  1869.     if (PRINTOFFSET) {
  1870.         if (agrep_finalfp != NULL)
  1871.             fprintf(agrep_finalfp, "@%d{%d} ", CurrentByteOffset - (i-bp), i-bp);
  1872.         else {
  1873.             char s[32];
  1874.             int outindex;
  1875.             sprintf(s, "@%d{%d} ", CurrentByteOffset - (i-bp), i-bp);
  1876.             for (outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  1877.                      (s[outindex] != '\0'); outindex ++) {
  1878.                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  1879.             }
  1880.             if (s[outindex] != '\0') {
  1881.                 OUTPUT_OVERFLOW;
  1882.                 return -1;
  1883.             }
  1884.             agrep_outpointer += outindex;
  1885.         }
  1886.         PRINTED = 1;
  1887.     }
  1888.     if (PRINTRECORD) {
  1889.     if (agrep_finalfp != NULL)
  1890.         while(bp <= i) fputc(buffer[bp++], agrep_finalfp);
  1891.     else {
  1892.         if (i - bp + 1 + agrep_outpointer >= agrep_outlen) {
  1893.             OUTPUT_OVERFLOW;
  1894.             return -1;
  1895.         }
  1896.         while(bp <= i) agrep_outbuffer[agrep_outpointer ++] = buffer[bp++];
  1897.     }
  1898.     }
  1899.     else if (PRINTED) {
  1900.         if (agrep_finalfp != NULL) fputc('\n', agrep_finalfp);
  1901.         else agrep_outbuffer[agrep_outpointer ++] = '\n';
  1902.         PRINTED = 0;
  1903.     }
  1904.  
  1905.     return 0;
  1906. }
  1907.  
  1908. /*
  1909.  * Processes the options specified in argc and argv, and fetches the pattern.
  1910.  * Also sets the set of filenames to be searched for internally. Returns: -1
  1911.  * if there is a serious error, 0 if there is no pattern or an error in getting
  1912.  * the file names, the length (> 0) of the pattern if there is no error. When a
  1913.  * 0 is returned, it means that at least the options were processed correctly.
  1914.  */
  1915. int
  1916. agrep_init(argc, argv, initialfd, pattern_len, pattern_buffer)
  1917.     int    argc;
  1918.     char    *argv[];
  1919.     int    initialfd;
  1920.     int    pattern_len;
  1921.     CHAR    *pattern_buffer;
  1922. {
  1923.     int i, j, seenlsq = 0;
  1924.     char c, *p;
  1925.     int filetype;
  1926.     char **original_argv = argv;
  1927.     char *home;
  1928.     int quitwhile;
  1929.     int NOOUTTAIL=OFF;
  1930.  
  1931.     initial_value();
  1932.  
  1933.     if (pattern_len < 1) {
  1934.         fprintf(stderr, "agrep_init: pattern length %d too small\n", pattern_len);
  1935.         errno = 3;
  1936.         return -1;
  1937.     }
  1938.     agrep_initialfd = initialfd;
  1939.     strncpy(Progname, argv[0], MAXNAME);
  1940.     if (argc < 2) return agrep_usage();
  1941.  
  1942.     Pattern[0] = '\0';
  1943.  
  1944.     while(--argc > 0 && (*++argv)[0] == '-') { /* argv is incremented automatically here */
  1945.         p = argv[0]+1;                 /* ptr to first character after '-' */
  1946.         c = *(argv[0]+1); 
  1947.         quitwhile = OFF;
  1948.         while(!quitwhile && (*p != '\0')) {
  1949.             c = *p;
  1950.             switch(c) {
  1951.             case 'z' :
  1952.                 NOOUTPUTZERO = ON;    /* don't output files with 0 matches */
  1953.                 PRINT(printf("z\n");
  1954.                 )
  1955.                     break;
  1956.  
  1957.             case 'c' : 
  1958.                 COUNT = ON;    /* output the # of matches */
  1959.                 PRINT(printf("c\n");
  1960.                 )
  1961.                     break;
  1962.  
  1963.             case 's' : 
  1964.                 SILENT = ON;   /* silent mode  */
  1965.                 PRINT(printf("s\n");
  1966.                 )
  1967.                     break;
  1968.  
  1969.             case 'p' : 
  1970.                 I = 0;         /* insertion cost is 0 */
  1971.                 PRINT(printf("p\n");
  1972.                 )
  1973.                     break; 
  1974.             case 'P' :
  1975.                 PRINTPATTERN = 1;    /* print pattern before every matched line */
  1976.                 PRINT(printf("p\n");
  1977.                 )
  1978.                     break;
  1979.  
  1980.             case 'x' : 
  1981.                 WHOLELINE = ON;  /* match the whole line */
  1982.                 PRINT(printf("x\n");
  1983.                 )
  1984.                     if(WORDBOUND) {
  1985.                         fprintf(stderr, "%s: illegal option combination (-x and -w)\n", Progname);
  1986.                         if (!EXITONERROR) {
  1987.                             errno = AGREP_ERROR;
  1988.                             return -1;
  1989.                         }
  1990.                         else exit(2);
  1991.                     }
  1992.                 break;
  1993.  
  1994.             case 'b' : 
  1995.                 BYTECOUNT = ON;
  1996.                 PRINT(printf("b\n");
  1997.                 )
  1998.                 break;
  1999.  
  2000.             case 'q' :
  2001.                 PRINTOFFSET = ON;
  2002.                 PRINT(printf("b\n");
  2003.                 )
  2004.                 break;
  2005.  
  2006.             case 'u' :
  2007.                 PRINTRECORD = OFF;
  2008.                 PRINT(printf("u\n");
  2009.                 )
  2010.                 break;
  2011.  
  2012.             case 'g' :
  2013.                 PRINTFILENUMBER = ON;
  2014.                 PRINT(printf("u\n");
  2015.                 )
  2016.                 break;
  2017.  
  2018.             case 'L' :
  2019.                 if ( *(p + 1) == '\0') {/* space after -L option */
  2020.                     if(argc <= 1) {
  2021.                         fprintf(stderr, "%s: the -L option must have an output-limit argument\n", Progname);
  2022.                         if (!EXITONERROR) {
  2023.                             errno = AGREP_ERROR;
  2024.                             return -1;
  2025.                         }
  2026.                         else exit(2);
  2027.                     }
  2028.                     argv++;
  2029.                     LIMITOUTPUT = LIMITTOTALFILE = LIMITPERFILE = 0;
  2030.                     sscanf(argv[0], "%d:%d:%d", &LIMITOUTPUT, &LIMITTOTALFILE, &LIMITPERFILE);
  2031.                     if ((LIMITOUTPUT < 0) || (LIMITTOTALFILE < 0) || (LIMITPERFILE < 0)) {
  2032.                         fprintf(stderr, "%s: invalid output limit %s\n", Progname, argv[0]);
  2033.                         if (!EXITONERROR) {
  2034.                             errno = AGREP_ERROR;
  2035.                             return -1;
  2036.                         }
  2037.                         else exit(2);
  2038.                     }
  2039.                     argc--;
  2040.                 } 
  2041.                 else {
  2042.                     LIMITOUTPUT = LIMITTOTALFILE = LIMITPERFILE = 0;
  2043.                     sscanf(p+1, "%d:%d:%d", &LIMITOUTPUT, &LIMITTOTALFILE, &LIMITPERFILE);
  2044.                     if ((LIMITOUTPUT < 0) || (LIMITTOTALFILE < 0) || (LIMITPERFILE < 0)) {
  2045.                         fprintf(stderr, "%s: invalid output limit %s\n", Progname, p+1);
  2046.                         if (!EXITONERROR) {
  2047.                             errno = AGREP_ERROR;
  2048.                             return -1;
  2049.                         }
  2050.                         else exit(2);
  2051.                     }
  2052.                 } /* else */
  2053.                 PRINT(printf("L\n");
  2054.                 )
  2055.                 quitwhile = ON;
  2056.                 break;
  2057.  
  2058.             case 'd' : 
  2059.                 DELIMITER = ON;  /* user defines delimiter */
  2060.                 PRINT(printf("d\n");
  2061.                 )
  2062.                 if ( *(p + 1) == '\0') {/* space after -d option */
  2063.                     if(argc <= 1) {
  2064.                         fprintf(stderr, "%s: the -d option must have a delimiter argument\n", Progname);
  2065.                         if (!EXITONERROR) {
  2066.                             errno = AGREP_ERROR;
  2067.                             return -1;
  2068.                         }
  2069.                         else exit(2);
  2070.                     }
  2071.                     argv++;
  2072.                     if ((D_length = strlen(argv[0])) > MaxDelimit) {
  2073.                         fprintf(stderr, "%s: delimiter pattern too long (has > %d chars)\n", Progname, MaxDelimit);
  2074.                         if (!EXITONERROR) {
  2075.                             errno = AGREP_ERROR;
  2076.                             return -1;
  2077.                         }
  2078.                         else exit(2);
  2079.                     }
  2080.                     D_pattern[0] = '<';
  2081.                     strcpy(D_pattern+1, argv[0]);
  2082.                     if (((argv[0][D_length-1] == '\n') || (argv[0][D_length-1] == '$') || (argv[0][D_length-1] == '^')) && (D_length == 1))
  2083.                         OUTTAIL = ON;
  2084.                     argc--;
  2085.                     PRINT(printf("space\n");
  2086.                     )
  2087.                 } 
  2088.                 else {
  2089.                     if ((D_length = strlen(p + 1)) > MaxDelimit) {
  2090.                         fprintf(stderr, "%s: delimiter pattern too long (has > %d chars)\n", Progname, MaxDelimit);
  2091.                         if (!EXITONERROR) {
  2092.                             errno = AGREP_ERROR;
  2093.                             return -1;
  2094.                         }
  2095.                         else exit(2);
  2096.                     }
  2097.                     D_pattern[0] = '<';
  2098.                     strcpy(D_pattern+1, p + 1);
  2099.                     if ((((p+1)[D_length-1] == '\n') || ((p+1)[D_length-1] == '$') || ((p+1)[D_length-1] == '^')) && (D_length == 1))
  2100.                         OUTTAIL = ON;
  2101.                 } /* else */
  2102.                 strcat(D_pattern, ">; ");
  2103.                 D_length++;   /* to count '<' as one */
  2104.                 PRINT(printf("D_pattern=%s\n", D_pattern);
  2105.                 )
  2106.                 strcpy(original_D_pattern, D_pattern);
  2107.                 original_D_length = D_length;
  2108.                 quitwhile = ON;
  2109.                 break;
  2110.  
  2111.             case 'H':
  2112.                 if (*(p + 1) == '\0') {/* space after - option */
  2113.                     if (argc <= 1) {
  2114.                         fprintf(stderr, "%s: a directory name must follow the -H option\n", Progname);
  2115.                         if (!EXITONERROR) {
  2116.                             errno = AGREP_ERROR;
  2117.                             return agrep_usage();
  2118.                         }
  2119.                         else exit(2);
  2120.                     }
  2121.                     argv ++;
  2122.                     strcpy(COMP_DIR, argv[0]);
  2123.                     argc --;
  2124.                 }
  2125.                 else {
  2126.                     strcpy(COMP_DIR, p+1);
  2127.                 }
  2128.                 quitwhile = ON;
  2129.                 break;
  2130.  
  2131.             case 'e' : 
  2132.                 if ( *(p + 1) == '\0') {/* space after -e option */
  2133.                     if(argc <= 1) {
  2134.                         fprintf(stderr, "%s: the -e option must have a pattern argument\n", Progname);
  2135.                         if (!EXITONERROR) {
  2136.                             errno = AGREP_ERROR;
  2137.                             return -1;
  2138.                         }
  2139.                         else exit(2);
  2140.                     }
  2141.                     argv++;
  2142.                     if(argv[0][0] == '-') {    /* not strictly necessary but no harm done */
  2143.                         Pattern[0] = '\\';
  2144.                         strcat(Pattern, (argv)[0]);
  2145.                     }
  2146.                     else strcat(Pattern, argv[0]);
  2147.                     argc--;
  2148.                 }
  2149.                 else {
  2150.                     if (*(p+1) == '-') {    /* not strictly necessary but no harm done */
  2151.                         Pattern[0] = '\\';
  2152.                         strcat(Pattern, p+1);
  2153.                     }
  2154.                     else strcat (Pattern, p+1);
  2155.                 } /* else */
  2156.  
  2157.                 PRINT(printf("Pattern=%s\n", Pattern);
  2158.                 )
  2159.                 pattern_index = abs(argv - original_argv);
  2160.                 quitwhile = ON;
  2161.                 break;
  2162.  
  2163.             case 'k' : 
  2164.                 CONSTANT = ON;
  2165.                 if ( *(p + 1) == '\0') {/* space after -e option */
  2166.                     if(argc <= 1) {
  2167.                         fprintf(stderr, "%s: the -k option must have a pattern argument\n", Progname);
  2168.                         if (!EXITONERROR) {
  2169.                             errno = AGREP_ERROR;
  2170.                             return -1;
  2171.                         }
  2172.                         else exit(2);
  2173.                     }
  2174.                     argv++;
  2175.                     strcat(Pattern, argv[0]);
  2176.                     if((argc > 2) && (argv[1][0] == '-')) {
  2177.                         fprintf(stderr, "%s: -k should be the last option in the command\n", Progname);
  2178.                         if (!EXITONERROR) {
  2179.                             errno = AGREP_ERROR;
  2180.                             return -1;
  2181.                         }
  2182.                         else exit(2);
  2183.                     }
  2184.                     argc--;
  2185.                 }
  2186.                 else {
  2187.                     if((argc > 1) && (argv[1][0] == '-')) {
  2188.                         fprintf(stderr, "%s: -k should be the last option in the command\n", Progname);
  2189.                         if (!EXITONERROR) {
  2190.                             errno = AGREP_ERROR;
  2191.                             return -1;
  2192.                         }
  2193.                         else exit(2);
  2194.                     }
  2195.                     strcat (Pattern, p+1);
  2196.                 } /* else */
  2197.  
  2198.                 pattern_index = abs(argv - original_argv);
  2199.                 quitwhile = ON;
  2200.                 break;
  2201.  
  2202.             case 'f' : 
  2203.                 if (PAT_FILE == ON) {
  2204.                     fprintf(stderr, "%s: multiple -f options\n", Progname);
  2205.                     if (multifd >= 0) close(multifd);
  2206.                     if (!EXITONERROR) {
  2207.                         errno = AGREP_ERROR;
  2208.                         return -1;
  2209.                     }
  2210.                     else exit(2);
  2211.                 }
  2212.                 if (PAT_BUFFER == ON) {
  2213.                     fprintf(stderr, "%s: -f and -m are incompatible\n", Progname);
  2214.                     if (multibuf != NULL) free(multibuf);
  2215.                     multibuf = NULL;
  2216.                     multilen = 0;
  2217.                     if (!EXITONERROR) {
  2218.                         errno = AGREP_ERROR;
  2219.                         return -1;
  2220.                     }
  2221.                     else exit(2);
  2222.                 }
  2223.                 PAT_FILE = ON;
  2224.                 PRINT(printf("f\n");
  2225.                 )
  2226.                 argv++;
  2227.                 argc--;
  2228.  
  2229.                 if (argv[0] == NULL) {
  2230.                     /* A -f option with a NULL file name is a NO-OP: stupid, but simplifies glimpse :-) */
  2231.                     PAT_FILE = OFF;
  2232.                     quitwhile = ON;
  2233.                     break;
  2234.                 }
  2235.  
  2236.                 if((multifd = open(argv[0], O_RDONLY)) < 0) {
  2237.                     PAT_FILE = OFF;
  2238.                     fprintf(stderr, "%s: can't open pattern file for reading: %s\n", Progname, argv[0]);
  2239.                     if (!EXITONERROR) {
  2240.                         errno = AGREP_ERROR;
  2241.                         return -1;
  2242.                     }
  2243.                     else exit(2);
  2244.                 }
  2245.                 PRINT(printf("file=%s\n", argv[0]);
  2246.                 )
  2247.                 strcpy(PAT_FILE_NAME, argv[0]);
  2248.                 if (prepf(multifd, NULL, 0) <= -1) {
  2249.                     close(multifd);
  2250.                     PAT_FILE = OFF;
  2251.                     fprintf(stderr, "%s: error in processing pattern file: %s\n", Progname, argv[0]);
  2252.                     if (!EXITONERROR) {
  2253.                         errno = AGREP_ERROR;
  2254.                         return -1;
  2255.                     }
  2256.                     else exit(2);
  2257.                 }
  2258.                 quitwhile = ON;
  2259.                 break;
  2260.  
  2261.             case 'm' :
  2262.                 if (PAT_BUFFER == ON) {
  2263.                     fprintf(stderr, "%s: multiple -m options\n", Progname);
  2264.                     if (multibuf != NULL) free(multibuf);
  2265.                     multilen = 0;
  2266.                     if (!EXITONERROR) {
  2267.                         errno = AGREP_ERROR;
  2268.                         return -1;
  2269.                     }
  2270.                     else exit(2);
  2271.                 }
  2272.                 if (PAT_FILE == ON) {
  2273.                     fprintf(stderr, "%s: -f and -m are incompatible\n", Progname);
  2274.                     if (multifd >= 0) close(multifd);
  2275.                     if (!EXITONERROR) {
  2276.                         errno = AGREP_ERROR;
  2277.                         return -1;
  2278.                     }
  2279.                     else exit(2);
  2280.                 }
  2281.                 PAT_BUFFER = ON;
  2282.                 PRINT(printf("m\n");
  2283.                 )
  2284.                 argv ++;
  2285.                 argc --;
  2286.  
  2287.  
  2288.                 if ((argv[0] == NULL) || ((multilen = strlen(argv[0])) <= 0)) {
  2289.                     /* A -m option with a NULL or empty pattern buffer is a NO-OP: stupid, but simplifies glimpse :-) */
  2290.                     PAT_BUFFER = OFF;
  2291.                     multilen = 0;
  2292.                     multibuf = NULL;
  2293.                 }
  2294.                 else {
  2295.                     multibuf = (char *)malloc(multilen + 2);
  2296.                     strcpy(multibuf, argv[0]);
  2297.                     PRINT(printf("patterns=%s\n", multibuf);
  2298.                     )
  2299.                     if (prepf(-1, multibuf, multilen) <= -1) {
  2300.                         free(multibuf);
  2301.                         multilen = 0;
  2302.                         PAT_BUFFER = OFF;
  2303.                         fprintf(stderr, "%s: error in processing pattern buffer\n", Progname);
  2304.                         if (!EXITONERROR) {
  2305.                             errno = AGREP_ERROR;
  2306.                             return -1;
  2307.                         }
  2308.                         else exit(2);
  2309.                     }
  2310.                 }
  2311.                 quitwhile = ON;
  2312.                 break;
  2313.  
  2314.             case 'h' : 
  2315.                 NOFILENAME = ON;
  2316.                 PRINT(printf("h\n");
  2317.                 )
  2318.                     break;
  2319.  
  2320.             case 'i' : 
  2321.                 NOUPPER = ON;
  2322.                 PRINT(printf("i\n");
  2323.                 )
  2324.                     break;
  2325.  
  2326.             case 'l' : 
  2327.                 FILENAMEONLY = ON;
  2328.                 PRINT(printf("l\n");
  2329.                 )
  2330.                     break;
  2331.  
  2332.             case 'n' : 
  2333.                 LINENUM = ON;  /* output prefixed by line no*/
  2334.                 PRINT(printf("n\n");
  2335.                 )
  2336.                     break;
  2337.  
  2338.             case 'r' : 
  2339.                 RECURSIVE = ON;
  2340.                 PRINT(printf("r\n");
  2341.                 )
  2342.                     break;
  2343.             
  2344.             case 'V' :
  2345.                 printf("\nThis is agrep version %s, %s.\n\n", AGREP_VERSION, AGREP_DATE);
  2346.                 return 0;
  2347.  
  2348.             case 'v' : 
  2349.                 INVERSE = ON;  /* output no-matched lines */
  2350.                 PRINT(printf("v\n");
  2351.                 )
  2352.                     break;
  2353.  
  2354.             case 't' : 
  2355.                 OUTTAIL = ON;  /* output from tail of delimiter */
  2356.                 PRINT(printf("t\n");
  2357.                 )
  2358.                     break;
  2359.  
  2360.             case 'o' : 
  2361.                 NOOUTTAIL = ON;  /* output from front of delimiter */
  2362.                 PRINT(printf("t\n");
  2363.                 )
  2364.                     break;
  2365.  
  2366.             case 'B' : 
  2367.                 BESTMATCH = ON;
  2368.                 PRINT(printf("B\n");
  2369.                 )
  2370.                     break;
  2371.  
  2372.             case 'w' : 
  2373.                 WORDBOUND = ON;/* match to words */
  2374.                 PRINT(printf("w\n");
  2375.                 )
  2376.                     if(WHOLELINE) {
  2377.                         fprintf(stderr, "%s: illegal option combination (-w and -x)\n", Progname);
  2378.                         if (!EXITONERROR) {
  2379.                             errno = AGREP_ERROR;
  2380.                             return -1;
  2381.                         }
  2382.                         else exit(2);
  2383.                     }
  2384.                 break;
  2385.  
  2386.             case 'y' : 
  2387.                 NOPROMPT = ON;
  2388.                 PRINT(printf("y\n");
  2389.                 )
  2390.                     break;
  2391.  
  2392.             case 'I' : 
  2393.                 I = atoi(p + 1);  /* Insertion Cost */
  2394.                 JUMP = ON;
  2395.                 quitwhile = ON;
  2396.                 break;
  2397.  
  2398.             case 'S' : 
  2399.                 S = atoi(p + 1);  /* Substitution Cost */
  2400.                 JUMP = ON;
  2401.                 quitwhile = ON;
  2402.                 break;
  2403.  
  2404.             case 'D' : 
  2405.                 DD = atoi(p + 1); /* Deletion Cost */
  2406.                 JUMP = ON;
  2407.                 quitwhile = ON;
  2408.                 break;
  2409.  
  2410.             case 'G' : 
  2411.                 FILEOUT = ON; 
  2412.                 COUNT = ON;
  2413.                 break;
  2414.  
  2415.             case 'A':
  2416.                 ALWAYSFILENAME = ON;
  2417.                 break;
  2418.  
  2419.             case 'O':
  2420.                 POST_FILTER = ON;
  2421.  
  2422.             case 'M':
  2423.                 MULTI_OUTPUT = ON;
  2424.  
  2425.             case 'Z': break;    /* no-op: used by glimpse */
  2426.             
  2427.             default  : 
  2428.                 if (isdigit(c)) {
  2429.                     APPROX = ON;
  2430.                     D = atoi(p);
  2431.                     if (D > MaxError) {
  2432.                         fprintf(stderr,"%s: the maximum number of errors is %d\n", Progname, MaxError);
  2433.                         if (!EXITONERROR) {
  2434.                             errno = AGREP_ERROR;
  2435.                             return -1;
  2436.                         }
  2437.                         else exit(2);
  2438.                     }
  2439.                     quitwhile = ON;    /* note that even a number should occur at the end of a group of options, as f & e */
  2440.                 }
  2441.                 else {
  2442.                     fprintf(stderr, "%s: illegal option  -%c\n",Progname, c);
  2443.                     return agrep_usage();
  2444.                 }
  2445.  
  2446.             } /* switch(c) */
  2447.             p ++;
  2448.         }
  2449.     } /* while (--argc > 0 && (*++argv)[0] == '-') */
  2450.  
  2451.     if (NOOUTTAIL == ON) OUTTAIL = OFF;
  2452.  
  2453.     if (COMP_DIR[0] == '\0') {
  2454.         if ((home = (char *)getenv("HOME")) == NULL) {
  2455.             getcwd(COMP_DIR, MAX_LINE_LEN-1);
  2456.             fprintf(stderr, "using working-directory '%s' to locate dictionaries\n", COMP_DIR);
  2457.         }
  2458.         else strncpy(COMP_DIR, home, MAX_LINE_LEN);
  2459.     }
  2460.  
  2461.     strcpy(FREQ_FILE, COMP_DIR);
  2462.     strcat(FREQ_FILE, "/");
  2463.     strcat(FREQ_FILE, DEF_FREQ_FILE);
  2464.     strcpy(HASH_FILE, COMP_DIR);
  2465.     strcat(HASH_FILE, "/");
  2466.     strcat(HASH_FILE, DEF_HASH_FILE);
  2467.     strcpy(STRING_FILE, COMP_DIR);
  2468.     strcat(STRING_FILE, "/");
  2469.     strcat(STRING_FILE, DEF_STRING_FILE);
  2470.     initialize_common(FREQ_FILE, 0);    /* no error msgs */
  2471.  
  2472.     if (FILENAMEONLY && NOFILENAME) {
  2473.         fprintf(stderr, "%s: -h and -l options are mutually exclusive\n",Progname);
  2474.     }
  2475.     if (COUNT && (FILENAMEONLY || NOFILENAME)) {
  2476.         FILENAMEONLY = OFF; 
  2477.         if(!FILEOUT) NOFILENAME = OFF;
  2478.     }
  2479.  
  2480.     if (!(PAT_FILE || PAT_BUFFER) && Pattern[0] == '\0') { /* Pattern not set with -e option */
  2481.         if (argc <= 0) {
  2482.             agrep_usage();
  2483.             return 0;
  2484.         }
  2485.         strcpy(Pattern, *argv); 
  2486.         pattern_index = abs(argv - original_argv);
  2487.         argc--;
  2488.         argv++;
  2489.     }
  2490.     /* if multi-pattern search, just ignore any specified pattern altogether: treat it as a filename */
  2491.  
  2492.     if (copied_from_argv) {
  2493.         for (i=0; i<Numfiles; i++) free(Textfiles[i]);
  2494.         if (Textfiles != NULL) free(Textfiles);
  2495.     }
  2496.     copied_from_argv = 0;
  2497.     Numfiles = 0; Textfiles = NULL;
  2498.     execfd = agrep_initialfd;
  2499.     if (argc <= 0)  /* check Pattern against stdin */
  2500.         execfd = 0;
  2501.     else {    /* filenames were specified as a part of the command line */
  2502.         if (!(Textfiles = (CHAR **)malloc(argc * sizeof(CHAR *) ))) {
  2503.             fprintf(stderr, "%s: malloc failure in %s:%d\n", Progname, __FILE__, __LINE__);
  2504.             if (!EXITONERROR) {
  2505.                 errno = AGREP_ERROR;
  2506.                 return 0;
  2507.             }
  2508.             else exit(2);
  2509.         }
  2510.         copied_from_argv = 1;    /* should I free Textfiles next time? */
  2511.         while (argc--)
  2512.         {    /* one or more filenames on command line -- put the valid filenames in a array of strings */
  2513.  
  2514.             if ((filetype = check_file(*argv)) == NOSUCHFILE) {
  2515.                 if (!glimpse_call) if (!glimpse_call) fprintf(stderr,"%s: '%s' no such file or directory\n",Progname,*argv);
  2516.                 argv++;
  2517.             }
  2518.             else { /* file is ascii*/
  2519.                 if (!(Textfiles[Numfiles] = (CHAR *)malloc((strlen(*argv)+2)))) {
  2520.                     fprintf(stderr, "%s: malloc failure in %s:%d\n", Progname, __FILE__, __LINE__);
  2521.                     if (!EXITONERROR) {
  2522.                         errno = AGREP_ERROR;
  2523.                         return 0;
  2524.                     }
  2525.                     else exit(2);
  2526.                 }
  2527.                 strcpy(Textfiles[Numfiles++], *argv++);
  2528.             } /* else */
  2529.         } /* while (argc--) */
  2530.         if (Numfiles <= 0) return 0;
  2531.         /* If user specified wrong filenames, then we quit rather than taking input from stdin! */
  2532.     } /* else */
  2533.  
  2534.     M = strlen(Pattern);
  2535.     if (M<=0) return 0;
  2536.     for (i=0; i<M; i++) {
  2537.         if (( ((unsigned char *)Pattern)[i] > USERRANGE_MIN) && ( ((unsigned char *)Pattern)[i] <= USERRANGE_MAX)) {
  2538.             fprintf(stderr, "Warning: pattern has some meta-characters interpreted by agrep!\n");
  2539.             break;
  2540.         }
  2541.         else if (Pattern[i] == '\\') i++;    /* extra */
  2542.         else if (Pattern[i] == '[') seenlsq = 1;
  2543.         else if ((Pattern[i] == '-') && !seenlsq) {
  2544.             for (j=M; j>=i; j--)
  2545.                 Pattern[j+1] = Pattern[j];    /* right shift including '\0' */
  2546.             Pattern[i] = '\\';    /* escape the - */
  2547.             M ++;
  2548.             i++;
  2549.         }
  2550.         else if (Pattern[i] == ']') seenlsq = 0;
  2551.     }
  2552.  
  2553.     if (M > pattern_len - 1) {
  2554.         fprintf(stderr, "%s: pattern '%s' does not fit in specified buffer\n", Progname, Pattern);
  2555.         errno = 3;
  2556.         return 0;
  2557.     }
  2558.     if (pattern_buffer != Pattern)    /* not from mem/file-agrep() */
  2559.         strncpy(pattern_buffer, Pattern, M+1); /* copy \0 */
  2560.     return M;
  2561. }
  2562.  
  2563. /*
  2564.  * User need not bother about initialfd.
  2565.  * Both functions return -1 on error, 0 if there was no pattern,
  2566.  * length (>=1) of pattern otherwise.
  2567.  */
  2568.  
  2569. int
  2570. memagrep_init(argc, argv, pattern_len, pattern_buffer)
  2571.     int    argc;
  2572.     char    *argv[];
  2573.     int    pattern_len;
  2574.     char    *pattern_buffer;
  2575. {
  2576.     return (agrep_init(argc, argv, -1, pattern_len, pattern_buffer));
  2577. }
  2578.  
  2579. int
  2580. fileagrep_init(argc, argv, pattern_len, pattern_buffer)
  2581.     int    argc;
  2582.     char    *argv[];
  2583.     int    pattern_len;
  2584.     char    *pattern_buffer;
  2585. {
  2586.     return (agrep_init(argc, argv, 3, pattern_len, pattern_buffer));
  2587. }
  2588.  
  2589. /* returns -1 on error, num of matches (>=0) otherwise */
  2590. int
  2591. agrep_search(pattern_len, pattern_buffer, initialfd, input_len, input, output_len, output)
  2592. int pattern_len; 
  2593. CHAR *pattern_buffer;
  2594. int initialfd;
  2595. int input_len;
  2596. void *input;
  2597. int output_len;
  2598. void *output;
  2599. {
  2600.     int    i;
  2601.     int    filetype;
  2602.     int    ret;
  2603.     int    pattern_has_changed = 1;
  2604.  
  2605.     if ((multifd == -1) && (multibuf == NULL) && (pattern_len < 1)) {
  2606.         fprintf(stderr, "%s: pattern length %d too small\n", Progname, pattern_len);
  2607.         errno = 3;
  2608.         return -1;
  2609.     }
  2610.     if (pattern_len >= MAXPAT) {
  2611.         fprintf(stderr, "%s: pattern '%s' too long\n", Progname, pattern_buffer);
  2612.         errno = 3;
  2613.         return -1;
  2614.     }
  2615.  
  2616.     /* courtesy: crd@hplb.hpl.hp.com */
  2617.     if (agrep_saved_pattern) {
  2618.         if (strcmp(agrep_saved_pattern, pattern_buffer)) {
  2619.             free(agrep_saved_pattern);
  2620.             agrep_saved_pattern = NULL;
  2621.         }
  2622.         else {
  2623.             pattern_has_changed = 0;
  2624.         }
  2625.     }
  2626.     if (! agrep_saved_pattern) {
  2627.         agrep_saved_pattern = (CHAR *)malloc(pattern_len+1);
  2628.         memcpy(agrep_saved_pattern, pattern_buffer, pattern_len);
  2629.         agrep_saved_pattern[pattern_len] = '\0';
  2630.  
  2631.     }
  2632.     if (!pattern_has_changed) {
  2633.         reinit_value_partial();
  2634.     }
  2635.     else {
  2636.         reinit_value();
  2637.         if (pattern_buffer != Pattern)    /* not from mem/file-agrep() */
  2638.             strncpy(Pattern, pattern_buffer, pattern_len+1); /* copy \0 */
  2639.         M = strlen(Pattern);
  2640.     }
  2641.  
  2642.     if (output == NULL) {
  2643.         fprintf(stderr, "%s: invalid output descriptor\n", Progname);
  2644.         return -1;
  2645.     }
  2646.     if (output_len <= 0) {
  2647.         agrep_finalfp = (FILE *)output;
  2648.         agrep_outlen = 0;
  2649.         agrep_outbuffer = NULL;
  2650.         agrep_outpointer = 0;
  2651.     }
  2652.     else {
  2653.         agrep_finalfp = NULL;
  2654.         agrep_outlen = output_len;
  2655.         agrep_outbuffer = (CHAR *)output;
  2656.         agrep_outpointer = 0;
  2657.     }
  2658.  
  2659.     agrep_initialfd = initialfd;
  2660.     execfd = initialfd;
  2661.     if (initialfd == -1) {
  2662.         agrep_inbuffer = (CHAR *)input;
  2663.         agrep_inlen = input_len;
  2664.         agrep_inpointer = 0;
  2665.     }
  2666.     else if ((input_len > 0) && (input != NULL)) {
  2667.         /* Copy the set of filenames into Textfiles */
  2668.         if (copied_from_argv) {
  2669.             for (i=0; i<Numfiles; i++) free(Textfiles[i]);
  2670.             if (Textfiles != NULL) free(Textfiles);
  2671.         }
  2672.         copied_from_argv = 0;
  2673.         Numfiles = 0; Textfiles = NULL;
  2674. #if    0
  2675.         if (!(Textfiles = (CHAR **)malloc(input_len * sizeof(CHAR *) ))) {
  2676.             fprintf(stderr, "%s: malloc failure in %s:%d\n", Progname, __FILE__, __LINE__);
  2677.             if (!EXITONERROR) {
  2678.                 errno = AGREP_ERROR;
  2679.                 return 0;
  2680.             }
  2681.             else exit(2);
  2682.         }
  2683. #else    /*0*/
  2684.         Textfiles = (CHAR **)input;
  2685. #endif    /*0*/
  2686.  
  2687.         while (input_len --)
  2688.         {    /* one or more filenames on command line -- put the valid filenames in a array of strings */
  2689.  
  2690.             if ((filetype = check_file(*(char **)input)) == NOSUCHFILE) {
  2691.                 if(filetype == NOSUCHFILE) if (!glimpse_call) fprintf(stderr,"%s: '%s' no such file or directory\n",Progname,*(char **)input);
  2692.                 input = (void *)(((long)input) + sizeof(char *));
  2693.             } 
  2694.             else { /* file is ascii*/
  2695. #if    0
  2696.                 if (!(Textfiles[Numfiles] = (CHAR *)malloc((strlen(*(char **)input)+2)))) {
  2697.                     fprintf(stderr, "%s: malloc failure in %s:%d\n", Progname, __FILE__, __LINE__);
  2698.                     if (!EXITONERROR) {
  2699.                         errno = AGREP_ERROR;
  2700.                         return 0;
  2701.                     }
  2702.                     else exit(2);
  2703.                 }
  2704.                 strcpy(Textfiles[Numfiles++], *((char **)input));
  2705. #else    /*0*/
  2706.                 Textfiles[Numfiles++] = *((CHAR **)input);
  2707. #endif    /*0*/
  2708.                 input = (void *)(((long)input) + sizeof(char *));
  2709.             } /* else */
  2710.         } /* while (argc--) */
  2711.         if (Numfiles <= 0) return 0;
  2712.         /* If user specified wrong filenames, then we quit rather than taking input from stdin! */
  2713.     }
  2714.     else if (Numfiles <= 0) execfd = 0;
  2715.     /* the old set of files (agrep_init) are used */
  2716.  
  2717. #if    0
  2718.     printf("agrep_search: pat=%s buf=%s\n", Pattern, ((agrep_initialfd == -1) && (agrep_inlen < 20)) ? agrep_inbuffer : NULL);
  2719. #endif    /*0*/
  2720.  
  2721.     if (pattern_has_changed) {
  2722.         if (-1 == checksg(Pattern, D, 1)) return -1;       /* check if the pattern is simple */
  2723.         strcpy(OldPattern, Pattern);
  2724.  
  2725.         if (SGREP == 0) {    /* complex pattern search */
  2726.             if (-1 == preprocess(D_pattern, Pattern)) return -1;
  2727.             strcpy(old_D_pat, D_pattern);
  2728.             /* fprintf(stderr, "agrep_search: len=%d pat=%s\n", strlen(Pattern), Pattern); */
  2729.             if(!AParse &&  ((M = maskgen(Pattern, D)) == -1)) return -1;
  2730.         }
  2731.         else {    /* sgrep too can handle delimiters */
  2732.             if (DELIMITER) {
  2733.                 /* D_pattern is "<PAT>; ", D_length is 1 + length of string PAT: see agrep.c/'d' */
  2734.                 preprocess_delimiter(D_pattern+1, D_length - 1, D_pattern, &D_length);
  2735.                 /* D_pattern is the exact stuff we want to match, D_length is its strlen */
  2736.                 if ((tc_D_length = quick_tcompress(FREQ_FILE,HASH_FILE,D_pattern,D_length,tc_D_pattern,MaxDelimit*2,TC_EASYSEARCH)) <= 0) {
  2737.                     strcpy(tc_D_pattern, D_pattern);
  2738.                     tc_D_length = D_length;
  2739.                 }
  2740.                 /* printf("sgrep's delim=%s,%d tc_delim=%s,%d\n", D_pattern, D_length, tc_D_pattern, tc_D_length); */
  2741.             }
  2742.             M = strlen(OldPattern);
  2743.         }
  2744.     }
  2745.  
  2746.     if (AParse)  {    /* boolean converted to multi-pattern search */
  2747.         int prepf_ret= 0;
  2748.         if (pattern_has_changed)
  2749.             prepf_ret= prepf(-1, multibuf, multilen);
  2750.         if (prepf_ret  <= -1) {
  2751.             if (AComplexBoolean) destroy_tree(AParse);
  2752.             AParse = 0;
  2753.             PAT_BUFFER = 0;
  2754.             if (multibuf != NULL) free(multibuf);    /* this was allocated for arbit booleans, not multipattern search */
  2755.             multilen = 0;
  2756.             /* Cannot free multifd here since that is always allocated for multipattern search */
  2757.             return -1;
  2758.         }
  2759.     }
  2760.     if (Numfiles > 1) FNAME = ON;
  2761.     if (NOFILENAME) FNAME = 0;
  2762.     if (ALWAYSFILENAME) FNAME = ON;    /* used by glimpse ONLY: 15/dec/93 */
  2763.  
  2764.     if (agrep_initialfd == -1) ret = exec(execfd, NULL);
  2765.     else if(RECURSIVE) ret = (recursive(Numfiles, Textfiles));
  2766.     else  ret = (exec(execfd, Textfiles));
  2767.     return ret;
  2768. }
  2769.  
  2770. /*
  2771.  * User need not bother about initialfd.
  2772.  * Both functions return -1 on error, 0 otherwise.
  2773.  */
  2774.  
  2775. int
  2776. memagrep_search(pattern_len, pattern_buffer, input_len, input_buffer, output_len, output)
  2777. int pattern_len;
  2778. char *pattern_buffer;
  2779. int input_len;
  2780. char *input_buffer;
  2781. int output_len;
  2782. void *output;
  2783. {
  2784.     return(agrep_search(pattern_len, pattern_buffer, -1, input_len, input_buffer, output_len, output));
  2785. }
  2786.  
  2787. int
  2788. fileagrep_search(pattern_len, pattern_buffer, file_num, file_buffer, output_len, output)
  2789. int pattern_len;
  2790. char *pattern_buffer;
  2791. int file_num;
  2792. char **file_buffer;
  2793. int output_len;
  2794. void *output;
  2795. {
  2796.     return(agrep_search(pattern_len, pattern_buffer, 3, file_num, file_buffer, output_len, output));
  2797. }
  2798.  
  2799. /*
  2800.  * The original agrep_run() routine was split into agrep_search and agrep_init
  2801.  * so that the interface with glimpse could be made cleaner: see glimpse.
  2802.  * Now, the user can specify an initial set of options, and use them in future
  2803.  * searches. If agrep_init does not find the pattern, options are still SET.
  2804.  * In fileagrep_search, the user can specify a NEW set of files to be searched
  2805.  * after the options are processed (this is used in glimpse).
  2806.  *
  2807.  * Both functions return -1 on error, 0 otherwise.
  2808.  *
  2809.  * The arguments are self explanatory. The pattern should be specified in
  2810.  * one of the argvs. Options too can be specified in one of the argvs -- it
  2811.  * is exactly as if the options are being given to agrep at run time.
  2812.  * The only restrictions are that the input_buffer should begin with a '\n'
  2813.  * and after its end, there must be valid memory to store a copy of the pattern.
  2814.  */
  2815.  
  2816. int
  2817. memagrep(argc, argv, input_len, input_buffer, output_len, output)
  2818. int argc; 
  2819. char *argv[];
  2820. int input_len;
  2821. char *input_buffer;
  2822. int output_len;
  2823. void *output;
  2824. {
  2825.     int    ret;
  2826.  
  2827.     if ((ret = memagrep_init(argc, argv, MAXPAT, Pattern)) < 0) return -1;
  2828.     else if ((ret == 0) && (multifd == -1) && (multibuf == NULL)) return -1;
  2829.     /* ^^^ because one need not specify the pattern on the cmd line if -f OR -m */
  2830.     return memagrep_search(ret, Pattern, input_len, input_buffer, output_len, output);
  2831. }
  2832.  
  2833. int
  2834. fileagrep(argc, argv, output_len, output)
  2835. int argc; 
  2836. char *argv[];
  2837. int output_len;
  2838. void *output;
  2839. {
  2840.     int    ret;
  2841.  
  2842.     if ((ret = fileagrep_init(argc, argv, MAXPAT, Pattern)) < 0) return -1;
  2843.     else if ((ret == 0) && (multifd == -1) && (multibuf == NULL)) return -1;
  2844.     /* ^^^ because one need not specify the pattern on the cmd line if -f OR -m */
  2845.     return fileagrep_search(ret, Pattern, 0, NULL, output_len, output);
  2846. }
  2847.  
  2848. /*
  2849.  * RETURNS: total number of matched lines in all files that were searched.
  2850.  *
  2851.  * The pattern(s) remain(s) constant irrespective of the number of files.
  2852.  * Hence, essentially, all the interface routines below have to be changed
  2853.  * so that they DONT do that preprocessing again and again for multiple
  2854.  * files. This bug was found while interfacing agrep with cast.
  2855.  *
  2856.  * At present, sgrep() has been modified to have another parameter,
  2857.  * "samepattern" that tells it whether the pattern is the same as before.
  2858.  * Other funtions too should have such a parameter and should not repeat
  2859.  * preprocessing for all patterns. Since preprocessing for a pattern to
  2860.  * be searched in compressed files is siginificant, this bug was found.
  2861.  *
  2862.  * - bgopal on 15/Nov/93.
  2863.  */
  2864. int
  2865. exec(fd, file_list)
  2866. int fd;
  2867. char **file_list;
  2868.     int i;
  2869.     char c[8];
  2870.     int ret = 0;    /* no error */
  2871.  
  2872.     if ((Numfiles > 1) && (NOFILENAME == OFF)) FNAME = ON;
  2873.     if ((-1 == compat())) return -1; /* check compatibility between options */
  2874.  
  2875.     if (fd <= 0) {
  2876.         TCOMPRESSED = ON;    /* there is a possibility that the data might be tuncompressible */
  2877.         if (!SetCurrentByteOffset) CurrentByteOffset = 0;
  2878.         if((fd == 0) && FILENAMEONLY) {
  2879.             fprintf(stderr, "%s: -l option is not compatible with standard input\n", Progname);
  2880.             if (!EXITONERROR) {
  2881.                 errno = AGREP_ERROR;
  2882.                 return -1;
  2883.             }
  2884.             else exit(2);  
  2885.         }
  2886.         if(PAT_FILE || PAT_BUFFER) mgrep(fd, AParse);
  2887.         else {
  2888.             if(SGREP) ret = sgrep(OldPattern, strlen(OldPattern), fd, D, 0);
  2889.             else      ret = bitap(old_D_pat, Pattern, fd, M, D);
  2890.         }
  2891.         if (ret <= -1) return -1;
  2892.         if (COUNT && ret) {    /* dirty solution for glimpse's -b! */
  2893.             if(INVERSE && (PAT_FILE || PAT_BUFFER)) {    /* inverse will never be set in glimpse */
  2894.                 if (agrep_finalfp != NULL)
  2895.                     fprintf(agrep_finalfp, "%d\n", total_line-(num_of_matched - prev_num_of_matched));
  2896.                 else {
  2897.                     char s[32];
  2898.                     int  outindex;
  2899.  
  2900.                     sprintf(s, "%d\n", total_line-(num_of_matched - prev_num_of_matched));
  2901.  
  2902.                     for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  2903.                             (s[outindex] != '\0'); outindex++) {
  2904.                         agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  2905.                     }
  2906.                     if (s[outindex] != '\0') {
  2907.                         OUTPUT_OVERFLOW;
  2908.                         return -1;
  2909.                     }
  2910.                     agrep_outpointer += outindex;
  2911.                 }
  2912.             }
  2913.             else {
  2914.                 if (agrep_finalfp != NULL)
  2915.                     fprintf(agrep_finalfp, "%d\n", (num_of_matched - prev_num_of_matched));
  2916.                 else {
  2917.                     char s[32];
  2918.                     int  outindex;
  2919.  
  2920.                     sprintf(s, "%d\n", (num_of_matched - prev_num_of_matched));
  2921.  
  2922.                     for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  2923.                             (s[outindex] != '\0'); outindex++) {
  2924.                         agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  2925.                     }
  2926.                     if (s[outindex] != '\0') {
  2927.                         OUTPUT_OVERFLOW;
  2928.                         return -1;
  2929.                     }
  2930.                     agrep_outpointer += outindex;
  2931.                 }
  2932.             }
  2933.         }
  2934.     }
  2935.     else {
  2936.         /* fd > 0 => Numfiles > 0 */
  2937.  
  2938.         for (i = 0; i < Numfiles; i++, close(fd)) {
  2939.             prev_num_of_matched = num_of_matched;
  2940.             if (!SetCurrentByteOffset) CurrentByteOffset = 0;
  2941.             if (!SetCurrentFileName) {
  2942.                 if (PRINTFILENUMBER) sprintf(CurrentFileName, "%d", i);
  2943.                 else strcpy(CurrentFileName, file_list[i]);
  2944.             }
  2945.             TCOMPRESSED = ON;
  2946.             if (!tuncompressible_filename(file_list[i], strlen(file_list[i]))) TCOMPRESSED = OFF;
  2947.             NEW_FILE = ON;
  2948.             if ((fd = open(file_list[i], O_RDONLY)) < /*=*/ 0) {
  2949.                 fprintf(stderr, "%s: can't open file for reading: %s\n",Progname, file_list[i]);
  2950.             } 
  2951.             else { 
  2952.                 if(PAT_FILE || PAT_BUFFER) mgrep(fd, AParse);
  2953.                 else {
  2954.                     if(SGREP) ret = sgrep(OldPattern, strlen(OldPattern), fd, D, i);
  2955.                     else      ret = bitap(old_D_pat, Pattern, fd, M, D);
  2956.                 }
  2957.                 if (ret <= -1) {
  2958.                     close(fd);
  2959.                     return -1;
  2960.                 }
  2961.                 if (num_of_matched - prev_num_of_matched > 0) {
  2962.                     NOMATCH = OFF;
  2963.                     files_matched ++;
  2964.                 }
  2965.  
  2966.                 if (COUNT && !FILEOUT) {
  2967.                     if( (INVERSE && (PAT_FILE || PAT_BUFFER)) && ((total_line - (num_of_matched - prev_num_of_matched)> 0) || !NOOUTPUTZERO) ) {
  2968.                         if(FNAME && (NEW_FILE || !POST_FILTER)) {
  2969.                             if (agrep_finalfp != NULL)
  2970.                                 fprintf(agrep_finalfp, "%s: %d\n", CurrentFileName, total_line - (num_of_matched - prev_num_of_matched));
  2971.                             else {
  2972.                                 char s[32];
  2973.                                 int  outindex;
  2974.  
  2975.                                 sprintf(s, ": %d\n", total_line - (num_of_matched - prev_num_of_matched));
  2976.  
  2977.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  2978.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  2979.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  2980.                                 }
  2981.                                 if (CurrentFileName[outindex] != '\0') {
  2982.                                     OUTPUT_OVERFLOW;
  2983.                                     close(fd);
  2984.                                     return -1;
  2985.                                 }
  2986.                                 agrep_outpointer += outindex;
  2987.  
  2988.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  2989.                                         (s[outindex] != '\0'); outindex++) {
  2990.                                     agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  2991.                                 }
  2992.                                 if (s[outindex] != '\0') {
  2993.                                     OUTPUT_OVERFLOW;
  2994.                                     close(fd);
  2995.                                     return -1;
  2996.                                 }
  2997.                                 agrep_outpointer += outindex;
  2998.                             }
  2999.                             NEW_FILE = OFF;
  3000.                         }
  3001.                         else if (!FNAME) {
  3002.                             if (agrep_finalfp != NULL)
  3003.                                 fprintf(agrep_finalfp, "%d\n", total_line - (num_of_matched - prev_num_of_matched));
  3004.                             else {
  3005.                                 char s[32];
  3006.                                 int  outindex;
  3007.  
  3008.                                 sprintf(s, "%d\n", total_line - (num_of_matched - prev_num_of_matched));
  3009.  
  3010.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3011.                                         (s[outindex] != '\0'); outindex++) {
  3012.                                     agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  3013.                                 }
  3014.                                 if (s[outindex] != '\0') {
  3015.                                     OUTPUT_OVERFLOW;
  3016.                                     close(fd);
  3017.                                     return -1;
  3018.                                 }
  3019.                                 agrep_outpointer += outindex;
  3020.                             }
  3021.                         }
  3022.                     }
  3023.                     else if ( !(INVERSE && (PAT_FILE || PAT_BUFFER)) && (((num_of_matched - prev_num_of_matched) > 0) || !NOOUTPUTZERO) ) {
  3024.                         /* inverse is always 0 in glimpse, so we always come here */
  3025.                         if(FNAME && (NEW_FILE || !POST_FILTER)) {
  3026.                             if (agrep_finalfp != NULL)
  3027.                                 fprintf(agrep_finalfp, "%s: %d\n", CurrentFileName, (num_of_matched - prev_num_of_matched)); 
  3028.                             else {
  3029.                                 char s[32];
  3030.                                 int  outindex;
  3031.  
  3032.                                 sprintf(s, ": %d\n", (num_of_matched - prev_num_of_matched));
  3033.  
  3034.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3035.                                         (CurrentFileName[outindex] != '\0'); outindex++) {
  3036.                                     agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  3037.                                 }
  3038.                                 if (CurrentFileName[outindex] != '\0') {
  3039.                                     OUTPUT_OVERFLOW;
  3040.                                     close(fd);
  3041.                                     return -1;
  3042.                                 }
  3043.                                 agrep_outpointer += outindex;
  3044.  
  3045.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3046.                                         (s[outindex] != '\0'); outindex++) {
  3047.                                     agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  3048.                                 }
  3049.                                 if (s[outindex] != '\0') {
  3050.                                     OUTPUT_OVERFLOW;
  3051.                                     close(fd);
  3052.                                     return -1;
  3053.                                 }
  3054.                                 agrep_outpointer += outindex;
  3055.                             }
  3056.                             NEW_FILE = OFF;
  3057.                         }
  3058.                         else if (!FNAME) {
  3059.                             if (agrep_finalfp != NULL)
  3060.                                 fprintf(agrep_finalfp, "%d\n", (num_of_matched - prev_num_of_matched));
  3061.                             else {
  3062.                                 char s[32];
  3063.                                 int  outindex;
  3064.  
  3065.                                 sprintf(s, "%d\n", (num_of_matched - prev_num_of_matched));
  3066.  
  3067.                                 for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3068.                                         (s[outindex] != '\0'); outindex++) {
  3069.                                     agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  3070.                                 }
  3071.                                 if (s[outindex] != '\0') {
  3072.                                     OUTPUT_OVERFLOW;
  3073.                                     close(fd);
  3074.                                     return -1;
  3075.                                 }
  3076.                                 agrep_outpointer += outindex;
  3077.                             }
  3078.                         }
  3079.                     }
  3080.                 }  /* if COUNT */
  3081.                 if(FILEOUT && (num_of_matched - prev_num_of_matched)) {
  3082.                     if (-1 == file_out(file_list[i])) {
  3083.                         close(fd);
  3084.                         return -1;
  3085.                     }
  3086.                 }
  3087.             } /* else */
  3088.             if (glimpse_clientdied) {
  3089.                 close(fd);
  3090.                 return -1;
  3091.             }
  3092.             if (agrep_finalfp != NULL) fflush(agrep_finalfp);
  3093.             if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  3094.                 ((LIMITTOTALFILE > 0) && (LIMITTOTALFILE <= files_matched))) {
  3095.                 close(fd);
  3096.                 break;    /* done */
  3097.             }
  3098.         }  /* for i < Numfiles */
  3099.  
  3100.         if(NOMATCH && BESTMATCH) {
  3101.             if(WORDBOUND || WHOLELINE || LINENUM || INVERSE) { 
  3102.                 SGREP = 0;    
  3103.                 if(-1 == preprocess(D_pattern, Pattern)) return -1;
  3104.                 strcpy(old_D_pat, D_pattern);
  3105.                 if((M = maskgen(Pattern, D)) == -1) return -1;
  3106.             }
  3107.             COUNT=ON; 
  3108.             D=1;
  3109.             while(D<M && D<=MaxError && (num_of_matched - prev_num_of_matched == 0)) {
  3110.                 for (i = 0; i < Numfiles; i++, close(fd)) {
  3111.                     prev_num_of_matched = num_of_matched;
  3112.                     CurrentByteOffset = 0;
  3113.                     if (PRINTFILENUMBER) sprintf(CurrentFileName, "%d", i);
  3114.                     else strcpy(CurrentFileName, file_list[i]);
  3115.                     NEW_FILE = ON;
  3116.                     if ((fd = open(Textfiles[i], O_RDONLY)) > 0) {
  3117.                         if(PAT_FILE || PAT_BUFFER) mgrep(fd, AParse);
  3118.                         else {
  3119.                             if(SGREP) ret = sgrep(OldPattern,strlen(OldPattern),fd,D, i);
  3120.                             else ret = bitap(old_D_pat,Pattern,fd,M,D);
  3121.                         }
  3122.                         if (ret <= -1) return -1;
  3123.                     }
  3124.                     if (glimpse_clientdied) {
  3125.                         close(fd);
  3126.                         return -1;
  3127.                     }
  3128.                     if (agrep_finalfp != NULL) fflush(agrep_finalfp);
  3129.                     if ((((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  3130.                          ((LIMITTOTALFILE > 0) && (LIMITTOTALFILE <= files_matched))) &&
  3131.                         (num_of_matched > prev_num_of_matched)) {
  3132.                         close(fd);
  3133.                         break;
  3134.                     }
  3135.                 }  /* for i < Numfiles */
  3136.                 D++;
  3137.             } /* while */
  3138.  
  3139.             if(num_of_matched - prev_num_of_matched > 0) {
  3140.                 D--; 
  3141.                 errno = D;    /* #of errors if proper return */
  3142.                 COUNT = 0;
  3143.  
  3144.                 if(num_of_matched - prev_num_of_matched == 1) fprintf(stderr,"%s: 1 word matches ", Progname);
  3145.                 else fprintf(stderr,"%s: %d words match ", Progname, num_of_matched - prev_num_of_matched);
  3146.                 if(D==1) fprintf(stderr, "within 1 error");
  3147.                 else fprintf(stderr, "within %d errors", D);
  3148.  
  3149.                 fflush(stderr);
  3150.  
  3151.                 if(NOPROMPT) fprintf(stderr, "\n");
  3152.                 else {
  3153.                     if(num_of_matched - prev_num_of_matched == 1) fprintf(stderr,"; search for it? (y/n)");
  3154.                     else fprintf(stderr,"; search for them? (y/n)");
  3155.                     c[0] = 'y';
  3156.                     if (!glimpse_isserver && (fgets(c, 4, stdin) == NULL)) goto CONT;
  3157.                     if(c[0] != 'y') goto CONT;
  3158.                 }
  3159.  
  3160.                 for (i = 0; i < Numfiles; i++, close(fd)) {
  3161.                     prev_num_of_matched = num_of_matched;
  3162.                     CurrentByteOffset = 0;
  3163.                     if (PRINTFILENUMBER) sprintf(CurrentFileName, "%d", i);
  3164.                     else strcpy(CurrentFileName, file_list[i]);
  3165.                     NEW_FILE = ON;
  3166.                     if ((fd = open(Textfiles[i], O_RDONLY)) > 0) {
  3167.                         if(PAT_FILE || PAT_BUFFER) mgrep(fd, AParse);
  3168.                         else {
  3169.                             if(SGREP) ret = sgrep(OldPattern,strlen(OldPattern),fd,D, i);
  3170.                             else ret = bitap(old_D_pat,Pattern,fd,M,D);
  3171.                         }
  3172.                         if (ret <= -1) {
  3173.                             close(fd);
  3174.                             return -1;
  3175.                         }
  3176.                     }
  3177.                     if (glimpse_clientdied) {
  3178.                         close(fd);
  3179.                         return -1;
  3180.                     }
  3181.                     if (agrep_finalfp != NULL) fflush(agrep_finalfp);
  3182.                     if (((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) ||
  3183.                         ((LIMITTOTALFILE > 0) && (LIMITTOTALFILE <= files_matched))) {
  3184.                         close(fd);
  3185.                         break;    /* done */
  3186.                     }
  3187.                 }  /* for i < Numfiles */
  3188.                 NOMATCH = 0;
  3189.             }
  3190.         }
  3191.     }
  3192. CONT:
  3193.     if(EATFIRST) {
  3194.         if (agrep_finalfp != NULL) fprintf(agrep_finalfp, "\n");
  3195.         else if (agrep_outpointer >= agrep_outlen) {
  3196.             OUTPUT_OVERFLOW;
  3197.             return -1;
  3198.         }
  3199.         else agrep_outbuffer[agrep_outpointer++] = '\n';
  3200.         EATFIRST = OFF;
  3201.     }
  3202.     if(num_of_matched - prev_num_of_matched > 0) NOMATCH = OFF;
  3203.     /* if(NOMATCH) return(0); */
  3204.     /*printf("exec=%d\n", num_of_matched);*/
  3205.     return(num_of_matched);
  3206.  
  3207. } /* end of exec() */
  3208.  
  3209.  
  3210. /* Just output the contents of the file fname onto the std output */
  3211. int
  3212. file_out(fname)
  3213. char *fname;
  3214. {
  3215.     int num_read;
  3216.     int fd;
  3217.     int i, len;
  3218.     CHAR buf[SIZE+2];
  3219.     if(FNAME) {
  3220.         len = strlen(fname);
  3221.         if (agrep_finalfp != NULL) {
  3222.             fputc('\n', agrep_finalfp);
  3223.             for(i=0; i< len; i++) fputc(':', agrep_finalfp);
  3224.             fputc('\n', agrep_finalfp);
  3225.             fprintf(agrep_finalfp, "%s\n", fname);
  3226.             for(i=0; i< len; i++) fputc(':', agrep_finalfp);
  3227.             fputc('\n', agrep_finalfp);
  3228.             fflush(agrep_finalfp);
  3229.         }
  3230.         else {
  3231.             if (1+len+1+len+1+len+1+agrep_outpointer >= agrep_outlen) {
  3232.                 OUTPUT_OVERFLOW;
  3233.                 return -1;
  3234.             }
  3235.             agrep_outbuffer[agrep_outpointer++] = '\n';
  3236.             for (i=0; i<len; i++) agrep_outbuffer[agrep_outpointer++] = ':';
  3237.             agrep_outbuffer[agrep_outpointer++] = '\n';
  3238.             for (i=0; i<len; i++) agrep_outbuffer[agrep_outpointer++] = fname[i];
  3239.             agrep_outbuffer[agrep_outpointer++] = '\n';
  3240.             for (i=0; i<len; i++) agrep_outbuffer[agrep_outpointer++] = ':';
  3241.             agrep_outbuffer[agrep_outpointer++] = '\n';
  3242.         }
  3243.     }
  3244.     fd = open(fname, O_RDONLY);
  3245.     if (agrep_finalfp != NULL) {
  3246.         while((num_read = fill_buf(fd, buf, SIZE)) > 0) 
  3247.             write(1, buf, num_read);
  3248.         if (glimpse_clientdied) {
  3249.             close(fd);
  3250.             return -1;
  3251.         }
  3252.     }
  3253.     else {
  3254.         if ((num_read = fill_buf(fd, agrep_outbuffer + agrep_outpointer, agrep_outlen - agrep_outpointer)) > 0)
  3255.             agrep_outpointer += num_read;
  3256.     }
  3257.     close(fd);
  3258.     return 0;
  3259. }
  3260.  
  3261. int
  3262. output(buffer, i1, i2, j)  
  3263. register CHAR *buffer; 
  3264. int i1, i2, j;
  3265. {
  3266.     int PRINTED = 0;
  3267.     register CHAR *bp, *outend;
  3268.     if(i1 > i2) return 0;
  3269.     num_of_matched++;
  3270.     if(COUNT)  return 0;
  3271.     if(SILENT) return 0;
  3272.     if(OUTTAIL || (!DELIMITER && (D_length == 1) && (D_pattern[0] == '\n')) ) {
  3273.         if (j>1) i1 = i1 + D_length;
  3274.         i2 = i2 + D_length;
  3275.     }
  3276.     if(DELIMITER) j = j+1;
  3277.     if(FIRSTOUTPUT) {
  3278.         if (buffer[i1] == '\n')  {
  3279.             i1++;
  3280.             EATFIRST = ON;
  3281.         }
  3282.         FIRSTOUTPUT = 0;
  3283.     }
  3284.     if(TRUNCATE) {
  3285.         fprintf(stderr, "WARNING!  some lines have been truncated in output record #%d\n", num_of_matched-1);
  3286.     }
  3287.  
  3288.     /* Why do we have to do this? */
  3289.     while ((buffer[i1] == '\n') && (i1 <= i2)) {
  3290.         if (agrep_finalfp != NULL) fprintf(agrep_finalfp, "\n");
  3291.         else {
  3292.             if (agrep_outpointer < agrep_outlen)
  3293.                 agrep_outbuffer[agrep_outpointer ++] = '\n';
  3294.             else {
  3295.                 OUTPUT_OVERFLOW;
  3296.                 return -1;
  3297.             }
  3298.         }
  3299.         i1++;
  3300.     }
  3301.  
  3302.     if(FNAME && (NEW_FILE || !POST_FILTER)) {
  3303.         char    nextchar = (POST_FILTER == ON)?'\n':' ';
  3304.         char    *prevstring = (POST_FILTER == ON)?"\n":"";
  3305.         if (agrep_finalfp != NULL)
  3306.             fprintf(agrep_finalfp, "%s%s:%c", prevstring, CurrentFileName, nextchar);
  3307.         else {
  3308.             int outindex;
  3309.             if (prevstring[0] != '\0') {
  3310.                 if(agrep_outpointer + 1 >= agrep_outlen) {
  3311.                     OUTPUT_OVERFLOW;
  3312.                     return -1;
  3313.                 }
  3314.                 else agrep_outbuffer[agrep_outpointer ++] = prevstring[0];
  3315.             }
  3316.             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3317.                     (CurrentFileName[outindex] != '\0'); outindex++) {
  3318.                 agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  3319.             }
  3320.             if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+2>=agrep_outlen)) {
  3321.                 OUTPUT_OVERFLOW;
  3322.                 return -1;
  3323.             }
  3324.             else {
  3325.                 agrep_outbuffer[agrep_outpointer+outindex++] = ':';
  3326.                 agrep_outbuffer[agrep_outpointer+outindex++] = nextchar;
  3327.             }
  3328.             agrep_outpointer += outindex;
  3329.         }
  3330.         NEW_FILE = OFF;
  3331.         PRINTED = 1;
  3332.     }
  3333.     if(LINENUM) {
  3334.         if (agrep_finalfp != NULL)
  3335.             fprintf(agrep_finalfp, "%d: ", j-1); 
  3336.         else {
  3337.             char s[32];
  3338.             int  outindex;
  3339.  
  3340.             sprintf(s, "%d: ", j-1);
  3341.             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3342.                     (s[outindex] != '\0'); outindex++) {
  3343.                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  3344.             }
  3345.             if (s[outindex] != '\0') {
  3346.                 OUTPUT_OVERFLOW;
  3347.                 return -1;
  3348.             }
  3349.             agrep_outpointer += outindex;
  3350.         }
  3351.         PRINTED = 1;
  3352.     }
  3353.     if(BYTECOUNT) {
  3354.         if (agrep_finalfp != NULL)
  3355.             fprintf(agrep_finalfp, "%d= ", CurrentByteOffset-1);
  3356.         else {
  3357.             char s[32];
  3358.             int  outindex;
  3359.             sprintf(s, "%d= ", CurrentByteOffset-1);
  3360.             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3361.                     (s[outindex] != '\0'); outindex++) {
  3362.                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  3363.             }
  3364.             if (s[outindex] != '\0') {
  3365.                 OUTPUT_OVERFLOW;
  3366.                 return -1;
  3367.             }
  3368.             agrep_outpointer += outindex;
  3369.         }
  3370.         PRINTED = 1;
  3371.     }
  3372.  
  3373.     bp = buffer + i1;
  3374.     outend = buffer + i2;
  3375.  
  3376.     if (PRINTOFFSET) {
  3377.         if (agrep_finalfp != NULL)
  3378.             fprintf(agrep_finalfp, "@%d{%d}\n", CurrentByteOffset - (i2-i1), i2-i1);
  3379.         else {
  3380.             char s[32];
  3381.             int outindex;
  3382.             sprintf(s, "@%d{%d}\n", CurrentByteOffset - (i2-i1), i2-i1);
  3383.             for (outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  3384.                      (s[outindex] != '\0'); outindex ++) {
  3385.                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  3386.             }
  3387.             if (s[outindex] != '\0') {
  3388.                 OUTPUT_OVERFLOW;
  3389.                 return -1;
  3390.             }
  3391.             agrep_outpointer += outindex;
  3392.         }
  3393.         PRINTED = 1;
  3394.     }
  3395.  
  3396.     if (PRINTRECORD) {
  3397.     if (agrep_finalfp != NULL)
  3398.         while(bp <= outend) fputc(*bp++, agrep_finalfp);
  3399.     else {
  3400.         if (outend - bp + 1 + agrep_outpointer >= agrep_outlen) {
  3401.             OUTPUT_OVERFLOW;
  3402.             return -1;
  3403.         }
  3404.         while(bp <= outend) agrep_outbuffer[agrep_outpointer ++] = *bp++;
  3405.     }
  3406.     }
  3407.     else if (PRINTED) {
  3408.         if (agrep_finalfp != NULL) fputc('\n', agrep_finalfp);
  3409.         else agrep_outbuffer[agrep_outpointer ++] = '\n';
  3410.         PRINTED = 0;
  3411.     }
  3412.     return 0;
  3413. }
  3414.  
  3415. int
  3416. agrep_usage()
  3417. {
  3418.     if (glimpse_call) return -1;
  3419.     fprintf(stderr, "usage: %s [-#abcdehiklnoprstvwxyBDGIMSV] [-f patternfile] [-H dir] pattern [files]\n", Progname); 
  3420.     fprintf(stderr, "\n");    
  3421.     fprintf(stderr, "summary of frequently used options:\n");
  3422.     fprintf(stderr, "(For a more detailed listing see 'man agrep'.)\n");
  3423.     fprintf(stderr, "-#: find matches with at most # errors\n");
  3424.     fprintf(stderr, "-c: output the number of matched records\n");
  3425.     fprintf(stderr, "-d: define record delimiter\n");
  3426.     fprintf(stderr, "-h: do not output file names\n");
  3427.     fprintf(stderr, "-i: case-insensitive search, e.g., 'a' = 'A'\n");
  3428.     fprintf(stderr, "-l: output the names of files that contain a match\n");
  3429.     fprintf(stderr, "-n: output record prefixed by record number\n");
  3430.     fprintf(stderr, "-v: output those records that have no matches\n");
  3431.     fprintf(stderr, "-w: pattern has to match as a word, e.g., 'win' will not match 'wind'\n");
  3432.     fprintf(stderr, "-B: best match mode. find the closest matches to the pattern\n"); 
  3433.     fprintf(stderr, "-G: output the files that contain a match\n");
  3434.     fprintf(stderr, "-H 'dir': the cast-dictionary is located in directory 'dir'\n");
  3435.     fprintf(stderr, "\n");    
  3436.  
  3437.     if (!EXITONERROR) {
  3438.         errno = AGREP_ERROR;
  3439.         return -1;
  3440.     }
  3441.     else exit(2);
  3442. }
  3443.